Ajout d'une chaîne HTML au DOM

121

Comment ajouter cette chaîne HTML

var str = '<p>Just some <span>text</span> here</p>';

au DIV avec l'ID 'test'qui se trouve dans le DOM?

(Btw div.innerHTML += str;n'est pas acceptable.)

Šime Vidas
la source

Réponses:

243

Utilisez-le insertAdjacentHTMLs'il est disponible, sinon utilisez une sorte de solution de secours. insertAdjacentHTML est pris en charge dans tous les navigateurs actuels .

div.insertAdjacentHTML( 'beforeend', str );

Démo en direct: http://jsfiddle.net/euQ5n/

Neil
la source
1
@alex C'est le même concept: analyser une chaîne HTML et la mettre dans le DOM. Mais la fonctionnalité est différente - innerHTMLmet la chaîne dans l'élément (en remplaçant tous les enfants), alors insertAdjacentHTMLqu'elle la met (1) avant l'élément, (2) après l'élément, (3) à l'intérieur de l'élément avant le premier enfant, ou (4) à l'intérieur de l'élément après le dernier enfant.
Šime Vidas
3
@alex insertAdjacentHTMLest plus rapide que l'ajout de innerHTML, car insertAdjacentHTMLil ne sérialise pas et n'analyse pas les enfants existants de l'élément.
hsivonen
2
En outre, insertAdjacentHTMLconserve les valeurs des éléments de formulaire modifiés, tandis que l'ajout à innerHTMLreconstruit l'élément et perd tout contexte de formulaire.
Brandon Gano
20

Est-ce acceptable?

var child = document.createElement('div');
child.innerHTML = str;
child = child.firstChild;
document.getElementById('test').appendChild(child);

jsFiddle .

Mais , la réponse de Neil est une meilleure solution.

Alex
la source
1
@ Šime Travailler avec l'API DOM ressemble toujours à un hack: P Préféreriez-vous désérialiser la chaîne sans innerHTML ?
alex le
Eh bien oui, s'il existe une autre façon d'utiliser l'analyseur HTML du navigateur, j'aimerais beaucoup savoir ...
Šime Vidas
1
@ Šime - Je pense qu'il n'y a que deux façons d'utiliser l'analyseur HTML du navigateur, innerHTML et document.write. Et si vous pensez que innerHTML est un hack ...
Alohci
@Alohci Il est une autre façon: insertAdjacentHTML.
Šime Vidas le
1
@ Šime -Merci. J'ai trouvé la version WHATWG. C'est dans la spécification d' analyse et de sérialisation DOM . Cela indique qu'en plus de innerHTML et insertAdjacentHTML, il y a externalHTML et, je pense, createContextualFragment.
Alohci
16

Performance

AppendChild(E) est plus de 2x plus rapide que les autres solutions sur Chrome et Safari, insertAdjacentHTML(F) est plus rapide sur Firefox. Le innerHTML=(B) (ne pas confondre avec+= (A)) est la deuxième solution rapide sur tous les navigateurs et il est beaucoup plus pratique que E et F.

Détails

Configuration de l'environnement (2019.07.10) MacOs High Sierra 10.13.4 sur Chrome 75.0.3770 (64 bits), Safari 11.1.0 (13604.5.6), Firefox 67.0.0 (64 bits)

entrez la description de l'image ici

  • sur Chrome E (140k opérations par seconde) est le plus rapide, B (47k) et F (46k) sont les seconds, A (332) est le plus lent
  • sur firefox F (94k) est le plus rapide, puis B (80k), D (73k), E (64k), C (21k) le plus lent est A (466)
  • sur Safari E (207k) est le plus rapide, puis B (89k), F (88k), D (83k), C (25k), le plus lent est A (509)

Vous pouvez rejouer le test sur votre machine ici

Kamil Kiełczewski
la source
12

L'idée est d'utiliser innerHTMLsur un élément intermédiaire, puis de déplacer tous ses nœuds enfants là où vous le souhaitez vraiment via appendChild.

var target = document.getElementById('test');
var str = '<p>Just some <span>text</span> here</p>';

var temp = document.createElement('div');
temp.innerHTML = str;
while (temp.firstChild) {
  target.appendChild(temp.firstChild);
}

Cela évite d'effacer les gestionnaires d'événements sur div#testmais vous permet toujours d'ajouter une chaîne de HTML.

Chris Calo
la source
3

La bonne façon est d'utiliser insertAdjacentHTML. Dans Firefox antérieur à 8, vous pouvez revenir à l'utilisation Range.createContextualFragmentsi votre strne contient aucune scriptbalise.

Si votre strcontient des scriptbalises, vous devez supprimer des scriptéléments du fragment renvoyé par createContextualFragmentavant d'insérer le fragment. Sinon, les scripts s'exécuteront. ( insertAdjacentHTMLmarque les scripts comme non exécutables.)

hsivonen
la source
Merci d'avoir mentionné createContextualFragment . Je cherchais un moyen de créer des inclusions HTML avec des scripts exécutés uniquement si l'utilisateur accepte de définir un cookie.
schliflo
3

Hack rapide :


<script>
document.children[0].innerHTML="<h1>QUICK_HACK</h1>";
</script>

Cas d'utilisation :

1: Enregistrez en tant que fichier .html et exécutez-le dans Chrome, Firefox ou Edge. (IE ne fonctionnera pas)

2: Utilisation dans http://js.do

En action: http://js.do/HeavyMetalCookies/quick_hack

Décomposé avec des commentaires:

<script>

//: The message "QUICK_HACK" 
//: wrapped in a header #1 tag.
var text = "<h1>QUICK_HACK</h1>";

//: It's a quick hack, so I don't
//: care where it goes on the document,
//: just as long as I can see it.
//: Since I am doing this quick hack in
//: an empty file or scratchpad, 
//: it should be visible.
var child = document.children[0];

//: Set the html content of your child
//: to the message you want to see on screen.
child.innerHTML = text;

</script>

Raison pour laquelle j'ai publié:

JS.do a deux incontournables:

  1. Pas de saisie semi-automatique
  2. Compatible moniteur vertical

Mais n'affiche pas les messages console.log. Je suis venu ici à la recherche d'une solution rapide. Je veux juste voir les résultats de quelques lignes de code de bloc-notes, les autres solutions sont trop de travail.

JMI MADISON
la source
1

Pourquoi n'est-ce pas acceptable?

document.getElementById('test').innerHTML += str

serait la manière classique de le faire.

Nick Brunt
la source
4
Cela tuerait les gestionnaires d'événements attachés à #testcependant. Ce n'est généralement pas souhaitable.
alex le
Intéressant qu'il le fasse. Cela ne semble pas vraiment logique.
Nick Brunt le
2
C'est logique, je suppose, si vous pensez à la sérialisation du HTML en une chaîne, puis à la réinitialisation du HTML.
alex le
Je suppose que JavaScript devrait être exécuté à nouveau pour réinitialiser le gestionnaire d'événements. C'est suffisant.
Nick Brunt le
1
@Nick Vous ne voulez pas stringifier (sérialiser) une partie du DOM juste pour pouvoir la concaténer avec une autre chaîne et ensuite analyser le tout dans le DOM. Comme alex l'a dit, la sérialisation n'enregistrera pas les gestionnaires d'événements liés (entre autres). Même si la sérialisation pouvait tout capturer, vous ne voudriez toujours pas le faire.
Šime Vidas
0

Cela peut résoudre

 document.getElementById("list-input-email").insertAdjacentHTML('beforeend', '<div class=""><input type="text" name="" value="" class="" /></div>');
Rafael Senne
la source
3
Bienvenue dans Stack overflow. Veuillez expliquer votre code dans le cadre d'une réponse pour fournir un contexte plutôt que de simplement coller une longue ligne de code. Bien que vous le compreniez, d'autres peuvent ne pas comprendre ce qu'il fait.
prêt.burger
0

InnerHTML efface toutes les données comme l'événement pour les nœuds existants

append child avec firstChild ajoute uniquement le premier enfant à innerHTML. Par exemple si nous devons ajouter:

 <p>text1</p><p>text2</p>

seul text1 apparaîtra

Et ça:

ajoute une balise spéciale à innerHTML en ajoutant un enfant, puis modifiez externalHTML en supprimant la balise que nous avons créée. Je ne sais pas à quel point c'est intelligent mais cela fonctionne pour moi ou vous pourriez changer externalHTML en innerHTML afin qu'il n'ait pas à utiliser la fonction de remplacement

function append(element, str)
{

  var child = document.createElement('someshittyuniquetag');
		
  child.innerHTML = str;

  element.appendChild(child);

  child.outerHTML = child.outerHTML.replace(/<\/?someshittyuniquetag>/, '');

// or Even child.outerHTML = child.innerHTML


  
}
<div id="testit">
This text is inside the div
<button onclick="append(document.getElementById('testit'), '<button>dadasasdas</button>')">To div</button>
<button onclick="append(this, 'some text')">to this</button>
</div>

Łukasz Szpak
la source
0

Le plus court - 18 caractères (à ne pas confondre +=(mention par OP) avec =plus de détails ici )

test.innerHTML=str

Kamil Kiełczewski
la source