jQuery document.createElement équivalent?

1251

Je refactorise un ancien code JavaScript et il y a beaucoup de manipulation DOM en cours.

var d = document;
var odv = d.createElement("div");
odv.style.display = "none";
this.OuterDiv = odv;

var t = d.createElement("table");
t.cellSpacing = 0;
t.className = "text";
odv.appendChild(t);

Je voudrais savoir s'il existe une meilleure façon de le faire en utilisant jQuery. J'ai expérimenté avec:

var odv = $.create("div");
$.append(odv);
// And many more

Mais je ne sais pas si c'est mieux.

Rob Stevenson-Leggett
la source
jsben.ch/#/ARUtz - une référence pour jquery vs createElement
EscapeNetscape
Duplication possible de la création d'un élément div dans jQuery
T.Todua
Uncaught TypeError: $ .create n'est pas une fonction
Tyguy7

Réponses:

1290

Voici votre exemple dans la ligne "un".

this.$OuterDiv = $('<div></div>')
    .hide()
    .append($('<table></table>')
        .attr({ cellSpacing : 0 })
        .addClass("text")
    )
;

Mise à jour : je pensais que je mettrais à jour ce message car il reçoit encore beaucoup de trafic. Dans les commentaires ci-dessous, il y a une discussion sur $("<div>")vs $("<div></div>")vs $(document.createElement('div'))comme moyen de créer de nouveaux éléments, et qui est "le meilleur".

J'ai mis en place une petite référence , et voici à peu près les résultats de la répétition des options ci-dessus 100 000 fois:

jQuery 1.4, 1.5, 1.6

               Chrome 11  Firefox 4   IE9
<div>            440ms      640ms    460ms
<div></div>      420ms      650ms    480ms
createElement    100ms      180ms    300ms

jQuery 1.3

                Chrome 11
<div>             770ms
<div></div>      3800ms
createElement     100ms

jQuery 1.2

                Chrome 11
<div>            3500ms
<div></div>      3500ms
createElement     100ms

Je pense que ce n'est pas une grosse surprise, mais document.createElementc'est la méthode la plus rapide. Bien sûr, avant de partir et de commencer à refactoriser l'intégralité de votre base de code, n'oubliez pas que les différences dont nous parlons ici (dans toutes les versions archaïques sauf jQuery) équivalent à environ 3 millisecondes supplémentaires pour mille éléments .


Update 2

Mis à jour pour jQuery 1.7.2 et mis le benchmark sur JSBen.chlequel est probablement un peu plus scientifique que mes benchmarks primitifs, en plus il peut être externalisé maintenant!

http://jsben.ch/#/ARUtz

nickf
la source
70
Vous constaterez que document.createElement est beaucoup plus rapide que d'avoir jQuery convertir votre chaîne html en un élément. (juste au cas où vous auriez envie de rendre les choses plus efficaces)
Sugendran
25
C'est vrai pour jQuery <1,3 C'est la vitesse équivalente maintenant je crois.
Rob Stevenson-Leggett
15
@Kevin, c'est vrai, cependant cela fait faire plus de travail à jQuery (il le fait passer par une expression régulière pour ajouter la balise de fermeture), donc je préfère la méthode ci-dessus. En outre, il différencie votre code $('div')dont il est visuellement très similaire, mais fonctionnellement différent.
nickf
14
Donc, fondamentalement, une combinaison de @Sungendran et @nickf serait $(document.createElement('div'))et devrait-elle être la plus rapide?
Kolky
14
Je pense que la façon "correcte" est $ ('<div />'), avec, IMO, a encore plus de "sens", car il est assez évident que vous créez un nœud. La mauvaise chose est de cette façon casse la mise en évidence de la syntaxe dans tous les éditeurs = (
Erik Escobedo
139

Le simple fait de fournir le code HTML des éléments que vous souhaitez ajouter à un constructeur jQuery $()renvoie un objet jQuery à partir du code HTML nouvellement construit, adapté pour être ajouté au DOM à l'aide de la append()méthode jQuery .

Par exemple:

var t = $("<table cellspacing='0' class='text'></table>");
$.append(t);

Vous pouvez ensuite remplir ce tableau par programme, si vous le souhaitez.

Cela vous donne la possibilité de spécifier n'importe quel code HTML arbitraire que vous aimez, y compris les noms de classe ou d'autres attributs, que vous pourriez trouver plus concis que d'utiliser createElementpuis de définir des attributs comme cellSpacinget classNamevia JS.

Adam Bellaire
la source
7
Cela était peut-être évident et indiqué par votre exemple, mais la création d'un élément DOM jQuery à l'aide de la syntaxe $ ("<html string>") ne peut pas être ajoutée au DOM à l'aide de la méthode native <element> .appendChild ou similaire. Vous devez utiliser la méthode d'ajout jQuery.
Adam
4
$(htmlStr)est implémenté en tant que document.createElement("div").innerHTML = htmlStr. En d'autres termes, il appelle l'analyseur HTML du navigateur. HTML mal formé se casse différemment dans IE par rapport aux autres navigateurs.
Matthew
2
L'objet @Adam jQuery a la getfonction qui renvoie l'élément DOM natif. (Je sais que ce sujet est ancien, mais je l'ajoute pour référence. ;-))
Constantino Tsarouhas
1
Si vous rencontrez des problèmes avec la chaîne html, essayez de l'analyser avec jQuery.parseHTML
fguillen
1
@Adam Ou, si c'est plus facile pour votre flux de code / vos yeux, vous pouvez le faire[dom element].appendChild($('<html>')[0]);
ACK_stoverflow
49

Je fais comme ça:

$('<div/>',{
    text: 'Div text',
    class: 'className'
}).appendTo('#parentDiv');
kami
la source
44

car jQuery1.8, utiliser $.parseHTML()pour créer des éléments est un meilleur choix.

il y a deux avantages:

1.si vous utilisez l'ancienne méthode, qui peut ressembler à quelque chose $(string), jQuery examinera la chaîne pour vous assurer que vous souhaitez sélectionner une balise html ou créer un nouvel élément. En utilisant $.parseHTML(), vous dites à jQuery que vous souhaitez créer un nouvel élément de manière explicite, donc les performances peuvent être un peu meilleures.

2.La chose la plus importante est que vous pouvez souffrir d'attaques intersites ( plus d'informations ) si vous utilisez l'ancienne méthode. si vous avez quelque chose comme:

    var userInput = window.prompt("please enter selector");
    $(userInput).hide();

un méchant peut entrer <script src="xss-attach.js"></script>pour vous taquiner. heureusement, $.parseHTML()évitez cet embarras pour vous:

var a = $('<div>')
// a is [<div>​</div>​]
var b = $.parseHTML('<div>')
// b is [<div>​</div>​]
$('<script src="xss-attach.js"></script>')
// jQuery returns [<script src=​"xss-attach.js">​</script>​]
$.parseHTML('<script src="xss-attach.js"></script>')
// jQuery returns []

Cependant, veuillez noter que ac'est un objet jQuery tandis que bc'est un élément html:

a.html('123')
// [<div>​123​</div>​]
b.html('123')
// TypeError: Object [object HTMLDivElement] has no method 'html'
$(b).html('123')
// [<div>​123​</div>​]
Brian
la source
«Un meilleur choix» pour «créer [tout] élément» pourrait être fort. La réponse de @ siergiej fait un bon travail de dire que parseHTMLc'est bon pour le html provenant de sources externes, mais que " tout le boost est parti après avoir encapsulé les résultats dans un nouvel objet jQuery ". Autrement dit, si vous voulez coder en dur la création d'un nouvel élément html enveloppé dans jQuery, le $("<div>stuff</div>")style semble toujours gagner.
ruffin
38

MISE À JOUR

Depuis les dernières versions de jQuery, la méthode suivante n'affecte pas les propriétés passées dans le deuxième objet

Réponse précédente

Je pense que l'utilisation document.createElement('div')avec jQueryest plus rapide:

$(document.createElement('div'), {
    text: 'Div text',
    'class': 'className'
}).appendTo('#parentDiv');
Om Shankar
la source
29

Bien que ce soit une très vieille question, j'ai pensé qu'il serait bien de la mettre à jour avec des informations récentes;

Depuis jQuery 1.8, il existe une fonction jQuery.parseHTML () qui est maintenant un moyen préféré de créer des éléments. En outre, il y a quelques problèmes avec l'analyse HTML via $('(html code goes here)'), par exemple le site Web officiel de jQuery mentionne ce qui suit dans l' une de leurs notes de version :

Analyse HTML détendue: vous pouvez à nouveau avoir des espaces de début ou des retours à la ligne avant les balises dans $ (htmlString). Nous vous conseillons toujours fortement d'utiliser $ .parseHTML () lors de l'analyse syntaxique du HTML obtenu à partir de sources externes, et nous apporterons peut-être d'autres modifications à l'analyse HTML à l'avenir.

Pour se rapporter à la question réelle, l'exemple fourni pourrait être traduit en:

this.$OuterDiv = $($.parseHTML('<div></div>'))
    .hide()
    .append($($.parseHTML('<table></table>'))
        .attr({ cellSpacing : 0 })
        .addClass("text")
    )
;

ce qui est malheureusement moins pratique que d'utiliser simplement $(), mais cela vous donne plus de contrôle, par exemple, vous pouvez choisir d'exclure les balises de script (cela laissera les scripts en ligne comme onclicksi):

> $.parseHTML('<div onclick="a"></div><script></script>')
[<div onclick=​"a">​</div>​]

> $.parseHTML('<div onclick="a"></div><script></script>', document, true)
[<div onclick=​"a">​</div>​, <script>​</script>​]

En outre, voici un point de repère de la réponse du haut ajusté à la nouvelle réalité:

Lien JSbin

jQuery 1.9.1

  $ .parseHTML: 88 ms
  $ ($. parseHTML): 240 ms
  <div> </div>: 138 ms
  <div>: 143 ms
  createElement: 64ms

Il semble être parseHTMLbeaucoup plus proche createElementque $(), mais tout le boost est parti après avoir enveloppé les résultats dans un nouvel objet jQuery

siergiej
la source
11
var mydiv = $('<div />') // also works
Shimon Doodkin
la source
6
var div = $('<div/>');
div.append('Hello World!');

Est le moyen le plus court / le plus simple de créer un élément DIV dans jQuery.

AcidicChip
la source
5

Je viens de créer un petit plugin jQuery pour cela: https://github.com/ern0/jquery.create

Il suit votre syntaxe:

var myDiv = $.create("div");

L'ID de noeud DOM peut être spécifié comme deuxième paramètre:

var secondItem = $.create("div","item2");

Est ce sérieux? Non. Mais cette syntaxe est meilleure que $ ("<div> </div>") , et c'est un très bon rapport qualité / prix.

Je suis un nouvel utilisateur de jQuery, passant de DOMAssistant, qui a une fonction similaire: http://www.domassistant.com/documentation/DOMAssistantContent-module.php

Mon plugin est plus simple, je pense que les attrs et le contenu sont mieux à ajouter en chaînant les méthodes:

$("#container").append( $.create("div").addClass("box").html("Hello, world!") );

C'est aussi un bon exemple pour un simple plugin jQuery (le 100e).

ern0
la source
4

C'est assez simple! Voici quelques exemples rapides ...


var $example = $( XMLDocRoot );

var $element = $( $example[0].createElement('tag') );
// Note the [0], which is the root

$element.attr({
id: '1',
hello: 'world'
});

var $example.find('parent > child').append( $element );
Excité
la source
1

Non mentionné dans les réponses précédentes, j'ajoute donc un exemple de travail pour créer des éléments avec la dernière jQuery, également avec des attributs supplémentaires comme le contenu, la classe ou le rappel onclick:

const mountpoint = 'https://jsonplaceholder.typicode.com/users'

const $button = $('button')
const $tbody = $('tbody')

const loadAndRender = () => {
  $.getJSON(mountpoint).then(data => {

    $.each(data, (index, { id, username, name, email }) => {
      let row = $('<tr>')
        .append($('<td>', { text: id }))
        .append($('<td>', {
          text: username,
          class: 'click-me',
          on: {
            click: _ => {
              console.log(name)
            }
          }
        }))
        .append($('<td>', { text: email }))

      $tbody.append(row)
    })

  })
}

$button.on('click', loadAndRender)
.click-me {
  background-color: lightgrey
}
<table style="width: 100%">
  <thead>
    <tr>
      <th>ID</th>
      <th>Username</th>
      <th>Email</th>
    </tr>
  </thead>
  <tbody>
  
  </tbody>
</table>

<button>Load and render</button>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

Vladislav Ladicky
la source
-2

jQuery out of the box n'a pas l'équivalent d'un createElement. En fait, la majorité du travail de jQuery se fait en interne en utilisant innerHTML sur une manipulation DOM pure. Comme Adam l'a mentionné ci-dessus, voici comment vous pouvez obtenir des résultats similaires.

Il existe également des plugins disponibles qui utilisent le DOM sur innerHTML comme appendDOM , DOMEC et FlyDOM pour n'en nommer que quelques-uns. En termes de performances, le jquery natif est toujours le plus performant (principalement parce qu'il utilise innerHTML)

James Hughes
la source
5
Vous devriez vous mettre à jour. jQuery n'utilise pas innerHtml mais analyse la chaîne HTML et construit en interne une arborescence DOM à l'aide de document.createElement (). Il s'agit du noyau jQuery.
Vincent Robert