web-dev-qa-db-fra.com

Manière la plus claire de construire des éléments HTML dans jQuery

J'ai vu beaucoup de styles différents (et peu de méthodes différentes) de création d'éléments dans jQuery. J'étais curieux de savoir comment le plus clair les construire, et aussi si une méthode particulière est objectivement meilleure qu'une autre pour une raison quelconque. Ci-dessous quelques exemples des styles et méthodes que j'ai vus.

var title = "Title";
var content = "Lorem ipsum";

// escaping endlines for a multi-line string
// (aligning the slashes is marginally prettier but can add a lot of whitespace)
var $element1 = $("\
    <div><h1>" + title + "</h1>\
        <div class='content'>  \
        " + content + "        \
        </div>                 \
    </div>                     \
");

// all in one
// obviously deficient
var $element2 = $("<div><h1>" + title + "</h1><div class='content'>" + content + "</div></div>");

// broken on concatenation
var $element3 = $("<div><h1>" +
                title + 
                "</h1><div class='content'>" +
                content +
                "</div></div>");

// constructed piecewise
// (I've seen this with nested function calls instead of temp variables)
var $element4 = $("<div></div>");
var $title = $("<h1></h1>").html(title);
var $content = $("<div class='content'></div>").html(content);
$element4.append($title, $content);

$("body").append($element1, $element2, $element3, $element4);

N'hésitez pas à démontrer d'autres méthodes/styles que vous pourriez utiliser.

67
bkconrad

Les modèles sont excellents et si vous y avez accès dans votre projet, je vous suggère de les utiliser. Si vous utilisez nderscore ou Lodash , il est intégré. Cependant, dans certains cas, vous aurez besoin de générer du HTML dans votre code, qu'il s'agisse de refactoring ou de test. J'ai trouvé que le format ci-dessous est le plus clair à lire lorsque c'est l'exigence.

Remarque: La spécification HTML autorise les guillemets simples OR) pour les attributs de votre balisage. Ne vous embêtez pas avec toutes les échappées fantastiques.

this.$fixture = $([
  "<div>",
  "  <div class='js-alert-box'></div>",
  "  <form id='my-form-to-validate'>",
  "    <input id='login-username' name='login-username'>",
  "  </form>",
  "</div>"
].join("\n"));
68
Baer

Après avoir regardé pendant un moment, j'ai trouvé le style sur lequel je me suis finalement installé. Tout d'abord, je dirai que j'ai utilisé Moustache pour créer des modèles, et cela a bien fonctionné. Parfois, cependant, vous devez simplement construire un élément une fois, sans le réutiliser, ou avoir une autre motivation pour ne pas importer une autre bibliothèque. Dans cette situation, j'ai commencé à utiliser:

$("body")
.append(
    $("<div>")
    .append(
        $("<div>")
        .append(
            $("<h1>").text(title)
        )
    )
    .append(
        $("<div>").text(content)
    )
);​

Cela fonctionne parce que append() renvoie une référence à l'objet que vous êtes en ajoutant à, donc chaîné append() s s'attache au même objet. Avec une bonne indentation, la structure du balisage est évidente et facile à modifier. Évidemment, c'est plus lent que d'utiliser des modèles (le tout doit être construit pièce par pièce), mais si vous ne l'utilisez que pour l'initialisation ou quelque chose de similaire, c'est un excellent compromis.

Une telle construction peut être formatée de nombreuses façons, mais j'ai choisi un moyen de clarifier ce qui se passe. La règle que j'ai utilisée est qu'il devrait y avoir au maximum une parenthèse ouvrante et/ou une parenthèse fermante sur chaque ligne. De plus, il n'est pas nécessaire de transmettre les feuilles de ces arbres annexes au constructeur jQuery, mais je l'ai déjà fait ici pour une répétition visuelle.

45
bkconrad

En ce qui concerne la construction du DOM, j'essaie d'éviter les concaténations de chaînes car elles pourraient conduire à des bogues subtils et à une sortie mal codée.

J'aime celui la:

$('<div/>', {
    html: $('<h1/>', {
        html: title
    }).after(
        $('<div/>', {
            'text': content,
            'class': 'content'
        })
    )
}).appendTo('body');

génère:

    ...
    <div><h1>some title</h1><div class="content">some content</div></div>
</body>

et il garantit un codage HTML correct et une construction d'arborescence DOM avec des balises d'ouverture et de fermeture correspondantes.

29
Darin Dimitrov

Mon conseil: n'essayez pas de construire des éléments html avec jQuery, ce n'est pas sa responsabilité.

Utilisez un système de templates Javascript comme Moustache ou HandlebarJs .

Avec un nombre de lignes très limité, vous pouvez créer vos éléments HTML directement à partir d'un objet Javascript. Ce n'est pas compliqué, seulement 2 fonctions et un modèle.

<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{body}}
  </div>
</div>

var context  = {title: "My New Post", body: "This is my first post!"}
var template = Handlebars.compile($("#template-skeleton"));
var html     = template(context);

Modifier:
Un autre exemple sans html, du Javascript pur (de ICanHaz ):

var skeleton = '<div><h1>{{title}}</h1><div class="content">{{content}}</div></div>';
var data = { title: "Some title", content: "Some content" };
var html = Mustache.to_html(skeleton, data);

C'est beaucoup plus facile à gérer qu'une série de concaténations.

23
Julien Lafont

2015 answer : pour les anciens navigateurs, utilisez multiline .

var str = multiline(function(){/*
<!doctype html>
<html>
    <body>
        <h1>❤ unicorns</h1>
    </body>
</html>
*/});

Pour ES6, utilisez chaînes de modèle JavaScript

var str = `
<!doctype html>
<html>
    <body>
        <h1>❤ unicorns</h1>
    </body>
</html>`
12
mikemaccana

Ceci est adapté de la réponse de Baer. Je le trouve plus lisible, pas besoin de créer et de rejoindre un tableau, pas besoin de mettre des guillemets autour de chaque ligne:

http://jsfiddle.net/emza5Ljb/

var html =

    '                                                           \
      <div>                                                     \
        <div class="js-alert-box"></div>                        \
        <form id="my-form-to-validate">                         \
          <input id="login-username" name="login-username">     \
        </form>                                                 \
      </div>                                                    \
    '

// using jQuery:
//
var dom = $( html )

// or if you need performance, don't use jQuery
// for the parsing.
// http://jsperf.com/create-dom-innerhtml-vs-jquery
//
var div       = document.createElement( 'div' )
div.innerHTML = html
var dom = $( div )

Pour votre information, lorsque les performances ne sont pas un problème et que les éléments contiennent beaucoup de données dynamiques, je ne fais parfois que écrire du code comme celui-ci (notez que le compilateur de clôture émettra un avertissement sur la propriété de classe non entre guillemets, mais cela fonctionne très bien dans les navigateurs modernes):

$(
      '<a></a>'

    , {
           text     : this.fileName
         , href     : this.fileUrl
         , target   : '_blank'
         , class    : 'file-link'
         , appendTo : this.container
      }
)
6
user1115652
2
Straseus

Je trouve l'approche fonctionnelle très pratique. Par exemple

// reusable generics TABLE constructor helpers
var TD = function(content) { return $('<td>', { html: content }) }
var TH = function(content) { return $('<th>', { html: content }) }
var TR = function(cell, cells) {  // note the kind of cell is a 2^order parameter
    return $('<tr>', { html: $.map(cells, cell) })
}

// application example
THEAD = $('<thead>', {html:
    TR(TH, [1,2,3,4])})
TBODY = $('<tbody>', {html: [
    TR(TD, ['a','b','c','d']),
    TR(TD, ['a','b','c','d']),
]})

maintenant l'appel

$('#table').append($('<table>', {html: [THEAD, TBODY]}))

les rendements

<table><thead><tr><th>1</th><th>2</th><th>3</th><th>4</th></tr></thead><tbody><tr><td>a</td><td>b</td><td>c</td><td>d</td></tr><tr><td>a</td><td>b</td><td>c</td><td>d</td></tr></tbody></table>

modifier

J'ai affiné mon approche, maintenant disponible par exemple sous la forme html_uty.js

2
CapelliC

Voici un exemple qui utilise $ (htmlString) et imite la disposition standard du code HTML:

function getPage(title, contents) {
  return (
    $("<div>", {id: "container", class: "box"}).append(
      $("<div>", {class: "title"}).append(
        $("<h1>").text(title)
      ),
      $("<div>").html(contents)
    )
  );
}
2
tokland