web-dev-qa-db-fra.com

Meilleure façon de créer des éléments HTML imbriqués avec jQuery

Si j'ai besoin de créer quelques éléments DOM imbriqués, je connais une façon de le faire, c'est de les écrire sous forme de chaîne longue, puis de les placer dans le document à l'aide d'une fonction jQuery appropriée. Quelque chose comme:

elem.html(
'<div class="wrapper">
    <div class="inner">
        <span>Some text<span>
    </div>
    <div class="inner">
        <span>Other text<span>
    </div>
</div>'); 

Cette façon n'est évidemment pas la plus propre. La piqûre ne prend pas trop de temps pour devenir salissante et l'édition devient un problème. Je préfère de beaucoup cette notation:

$('<div></div>', {
    class : 'inner'
})
.appendTo( elem );

Le problème est que je ne sais pas comment l'implémenter efficacement lors de la création d'éléments imbriqués à la volée comme ci-dessus. Donc, s'il y a moyen de faire le 1er exemple avec la 2ème notation, je serai heureux de l'apprendre.

Fondamentalement, la question est, quelle est la meilleure façon de créer des éléments HTML imbriqués à la volée, sans avoir à traiter avec de longues chaînes désordonnées?

Remarque: je connais les moteurs de modèles. Cependant, c'est une question concernant la création de quelques éléments HTML à la volée. Comme lors de la construction des dépendances DOM pour un plugin ou des cas similaires.

49
Maverick

écrivez-les sous forme de chaîne longue et placez-les dans le document à l'aide d'une fonction jQuery appropriée. Quelque chose comme:

Le problème avec cette approche est que vous aurez besoin d'une chaîne multi-lignes - quelque chose que Javascript ne prend pas en charge - donc en réalité vous vous retrouverez avec:

elem.html(
'<div class="wrapper">'+
    '<div class="inner">'+
        '<span>Some text<span>'+
    '</div>'+
    '<div class="inner">'+
        '<span>Other text<span>'+
    '</div>'+
'</div>');

En utilisant la méthode que vous avez suggérée ci-dessus, c'est à peu près aussi propre que possible pour l'obtenir:

elem.append(
    $('<div/>', {'class': 'wrapper'}).append(
        $('<div/>', {'class': 'inner'}).append(
            $('<span/>', {text: 'Some text'})
        )
    )
    .append(
        $('<div/>', {'class': 'inner'}).append(
            $('<span/>', {text: 'Other text'})
        )
    )
);

L'autre avantage de cette opération est que vous pouvez (si vous le souhaitez) obtenir des références directes à chaque élément nouvellement créé sans avoir à réinterroger le DOM.

J'aime écrire polyglottes , donc pour rendre mon code réutilisable, je fais habituellement quelque chose comme ça, (comme .html() de jQuery ne supporte pas XML):

// Define shorthand utility method
$.extend({
    el: function(el, props) {
        var $el = $(document.createElement(el));
        $el.attr(props);
        return $el;
    }
});

elem.append(
    $.el('div', {'class': 'wrapper'}).append(
        $.el('div', {'class': 'inner'}).append(
            $.el('span').text('Some text')
        )
    )
    .append(
        $.el('div', {'class': 'inner'}).append(
            $.el('span').text('Other text')
        )
    )
);

Ce n'est pas très différent de la méthode # 2 mais cela vous donne plus de code portable et ne dépend pas en interne de innerHTML.

59
lucideer

J'aime moi-même l'approche suivante:

$('<div>',{
  'class' : 'wrapper',
  'html': $('<div>',{
    'class' : 'inner',
    'html' : $('<span>').text('Some text')
  }).add($('<div>',{
    'class' : 'inner',
    'html' : $('<span>').text('Other text')
  }))
}).appendTo('body');

Alternativement, créez d'abord votre wrapper et continuez à y ajouter:

var $wrapper = $('<div>',{
    'class':'wrapper'
}).appendTo('body');
$('<div>',{
    'class':'inner',
    'html':$('<span>').text('Some text')
}).appendTo($wrapper);
$('<div>',{
    'class':'inner',
    'html':$('<span>').text('Other text')
}).appendTo($wrapper);
20
Brad Christie

J'ai trouvé cette solution pendant que je recherchais autre chose. Cela fait partie d'un "Introduction à jQuery" par le créateur de jQuery et utilise la fonction end () .

$("<li><a></a></li>") // li 
  .find("a") // a 
  .attr("href", "http://ejohn.org/") // a 
  .html("John Resig") // a 
  .end() // li 
  .appendTo("ul");

Appliquant à votre question ce serait ...

$("<div><span></span></div>") // div 
  .addClass("inner") // div 
  .find("span") // span 
  .html("whatever you want here.") // span 
  .end() // div 
  .appendTo( elem ); 
19
Hugh Chapman

J'aime cette approche

    $("<div>", {class: "wrapper"}).append(
        $("<div>", {class: "inner"}).append(
            $("<span>").text(
                "Some text"
            )
        ), 
        $("<div>", {class: "inner"}).append(
            $("<span>").text(
                "Some text"
            )
        )
    ).appendTo("body")
7
matt3141

Il existe une troisième voie en plus des longues cordes laides ou des méthodes énormes enchaînées. Vous pouvez utiliser simples anciennes variables pour contenir les éléments individuels :

var $wrapper = $("<div/>", { class: "wrapper" }),
    $inner = $("<p/>", { class: "inner" }),
    $text = $("<span/>", { class: "text", text: "Some text" });

Ensuite, liez le tout avec append:

$wrapper.append($inner.append($text)).appendTo("#whatever");

Résultat:

<div class="wrapper">
  <p class="inner">
    <span class="text">Some text</span>
  </p>
</div>

À mon avis, c'est de loin l'approche la plus propre et la plus lisible, et elle a également l'avantage de séparer les données du code.

EDIT: Une mise en garde, cependant, est qu'il n'y a pas de moyen facile de mélanger textContent avec des éléments imbriqués (par exemple, <p>Hello, <b>world!</b></p>.) Dans ce cas, vous auriez probablement besoin d'utiliser l'une des autres techniques telles qu'un littéral de chaîne.

7
jackvsworld

La longue chaîne est évidemment la manière la plus propre possible. Vous voyez le code correctement imbriqué sans tous ces bruits supplémentaires inutiles comme les crochets, les signes dollar et autres. Bien sûr, ce serait avantageux de pouvoir l'écrire sous forme de chaîne multiligne, mais ce n'est pas possible pour l'instant. Pour moi, il s'agit de se débarrasser de tous les symboles inutiles. Je ne sais pas comment la chaîne devient désordonnée et l'édition devient un problème. Si vous avez assigné beaucoup de classes, vous pouvez les mettre sur une ligne distincte:

'<div id="id-1"'
+ ' class="class-1 class-2 class-3 class-4 class-5 class-6">'
+ '</div>'

ou de cette façon:

'<div id="id-1" class="'
    + 'class-1 class-2 class-3 class-4 class-5 class-6'
+ '">'
+ '</div>'

Une autre option est probablement d'utiliser haml côté client, si cela est possible. De cette façon, vous aurez encore moins de bruit inutile.

1
x-yuri