2010-10-26 7 views
2

J'ai remarqué un comportement amusant et je me demandais si quelqu'un pouvait éclaircir la raison.JS: innerHTML et DOM ne coopèrent pas

Il se décompose comme suit:

  • J'ai ajouté un div et un button en utilisant `la appendChild de Javascript.
  • ajouter un gestionnaire onclick au bouton, fonctionne très bien
  • -je ajouter la cession ou céder la innerHTML du div pour ajouter un peu plus de contenu
  • Bouton onclick cesse de fonctionner tout à fait

Voici un exemple de script:

var D = document.createElement("DIV"), B = document.createElement("BUTTON"); 
B.innerHTML = "Is it true?"; 
document.body.appendChild(D); 
D.appendChild(B); 

B.onclick = function() { alert("Elvis Lives!"); } 

À ce stade, cela fonctionne très bien. Ensuite, ajoutez cette ligne: ...

D.innerHTML += "What about Tupac?"; 

... et le bouton se casse. Donc, je suis en train d'utiliser appendChild pour tous les éléments maintenant.

Mais -

  • Pourquoi est-ce qui se passe (« semble que cela devrait fonctionner :) »)
  • Y at-il une solution (en plus de tous mes éléments annexant supplémentaires)?

Répondre

3

innerHTML est un raccourci pour créer des éléments DOM.Lorsque vous ajoutez quelque chose à la div externe en utilisant innerHTML, voici ce qui se passe:

D.innerHTML += "What about Tupac?"; 

qui est le même que,

D.innerHTML = D.innerHTML + "What about Tupac?"; 

qui est le même que,

D.innerHTML = "<button>Is it true?</button>" + "What about Tupac?"; 

qui devient finalement ceci,

D.innerHTML = "<button>Is it true?</button>What about Tupac?"; 

Maintenant dans la dernière étape, nous avons complètement remplacé le contenu existant de la div, avec une nouvelle chaîne qui contient du HTML. En ce qui concerne le DOM, il ne se soucie pas de savoir si un utilisateur a tapé le HTML à la main, ou s'il vient d'appeler innerHTML sur un nœud DOM. Tout ce qui l'intéresse est, c'est qu'il a une chaîne de HTML, qui doit être convertie en DOM. Un nouvel élément de bouton est créé à ce moment-là, c'est pourquoi le onclick cesse de fonctionner - ce n'est plus le même élément.

+0

BAM sur la tête. Merci. – Ben

1

Pas une réponse, juste une page de test - semble très étrange - je peux confirmer vos résultats

<script> 
window.onload=function() { 
    var D = document.createElement("DIV"), B = document.createElement("BUTTON"); 
    D.id = "div1" 
    B.innerHTML = "Is it true?"; 
    B.onclick = function() { alert("Elvis Lives!"); } 
    D.appendChild(B); 
    document.body.appendChild(D); 
} 
</script> 
<a href="" onclick="document.getElementById('div1').innerHTML += 'What about Tupac?'; return false">Click</a><br> 
<a href="" onclick="alert(document.getElementsByTagName('button')[0].onclick); return false">Test</a> 

mise à jour: Leçons apprises - être cohérent.

Cela fonctionne comme prévu

<script> 
window.onload=function() { 
    var D = document.createElement("DIV"); 
    D.id = "div1" 
    D.innerHTML = '<button onclick="alert(\'Elvis Lives!\')">Elvis</button>' 
    document.body.appendChild(D); 
} 
</script> 
<a href="" onclick="document.getElementById('div1').innerHTML += 'What about Tupac?'; return false">Click</a><br> 
+0

Je ne peux pas m'abaisser à même d'entrevoir une page étrange! Quel est ce schlock? :) Je rigole. Merci pour la confirmation ... – Ben

4

(c'est beaucoup de deviner instruits) Je pense que lorsque vous modifiez l » innerHTMLD, le Royaume au sein D est détruit et créé à partir de la nouvelle valeur. Ainsi, lorsque les nouveaux contenus sont construits, vous obtenez un nouveau button, qui n'est pas le même nœud que B. Puisque vous définissez le gestionnaire onclick via js et non par un attribut sur l'élément d'origine, le nouveau button n'a pas cette référence de fonction. Cependant B fonctionne toujours comme on peut le démontrer en appelant

B.click(); 

après que vous ajoutez à innerHTML.

pour éviter la raclée du Royaume au sein de D, vous pouvez le faire au lieu d'utiliser innerHTML:

D.appendChild(document.createTextNode("What about Tupac?")); 
+1

Cela me semble bon mais je peux attendre quelques autres avis. À droite, j'utilise 'appendChild' partout, mais' innerHTML' est juste quelques lignes plus facile ... – Ben

+0

Pas besoin d'attendre. La réponse de Lincoln est la bonne. –

Questions connexes