59 votes

jQuery - Meilleure pratique pour la création de fragments HTML complexes

Existe-t-il une meilleure pratique générale pour créer des éléments HTML quelque peu complexes dans jQuery ? J'ai essayé plusieurs méthodes différentes.

J'ai d'abord essayé d'utiliser createElement et d'enchaîner plusieurs de ces éléments avec AppendTo et autres :

var badge = $(document.createElement("div")).attr("class", "wrapper1").appendTo("body");
$(document.createElement("div")).attr("class", "wrapper2").appendTo(".wrapper1");
$(document.createElement("table")).attr("class", "badgeBody").appendTo(".wrapper2");
$(document.createElement("tr")).attr("class", "row1").appendTo(".badgeBody");
$(document.createElement("td")).appendTo(".row1");
$(document.createElement("span")).attr("class", "badgeUnlocked").text("UNLOCKED! ").appendTo("td");
$(document.createElement("td")).attr("class", "badgeTitleText").appendTo(".row1");
$(document.createElement("span")).attr("class", "badgeTitle").text(name).appendTo(".badgeTitleText");
$(document.createElement("tr")).attr("class", "row2").appendTo(".badgeBody");
$(document.createElement("td")).appendTo(".row2");
$(document.createElement("img")).attr("src", imgUrl).appendTo(".row2 td");
$(document.createElement("td")).attr("class", "badgeText").appendTo(".row2");
$(document.createElement("span")).attr("class", "badgeDescription").text(description).appendTo(".badgeText");

Cela peut être difficile car appendTo veut ajouter à chaque élément correspondant, donc chaque élément doit avoir son propre nom, sinon il finira par être ajouté de manière répétée partout.

J'ai ensuite essayé de créer un tableau et de le joindre :

var badgeFragment = [
'<div><div id="'+ closeId+'" class="closeTab">X</div>',
'<div id="'+ badgeId+'" class="wrapper1">',
'<div class="wrapper2">',
'<div class="badgeBody">',
'<div class="badgeImage">',
'<img src="'+ imgUrl +'">',
'</div>',
'<div class="badgeContents">',
'<div class="badgeUnlocked">ACHIEVEMENT UNLOCKED: </div>',
'<div class="badgeTitle">'+ name +'</div>',
'<div id="'+ textId+'" class="badgeDescription">'+ description +'</div>',
'</div>',
'<div style="clear:both"></div>',
'</div></div></div></div></div>',
]

badgeFragment = $(badgeFragment.join(''));

Cela semble fonctionner assez bien, bien que dans IE, lorsque je mettais un alert($(badgeFragment).text()), il revenait généralement vide. (Cela faisait partie du débogage d'un problème plus important). Je suis évidemment un peu novice en matière de jQuery (et même de Javascript en fait), alors pour m'assurer que ce n'était pas le problème, j'ai essayé une troisième méthode : la concaténation géante de chaînes de caractères :

var badgeFragment =
'<div><div id="'+ closeId+'" class="closeTab">X</div>' +
'<div id="'+ badgeId+'" class="wrapper1">' +
'<div class="wrapper2">' +
'<div class="badgeBody">' +
'<div class="badgeImage">' +
'<img src="C:/Users/Ryan/Documents/icons/crystal_project/64x64/apps/chat.png">' +
'</div>' +
'<div class="badgeContents">' +
'<div class="badgeUnlocked">ACHIEVEMENT UNLOCKED: </div>' +
'<div class="badgeTitle">test</div>' +
'<div id="'+ textId+'" class="badgeDescription">test</div>' +
'</div>' +
'<div style="clear:both"></div>' +
'</div></div></div></div></div>';

L'une de ces méthodes est-elle généralement considérée comme meilleure que les autres ? Je ne suis pas très doué avec les différents profileurs, donc je ne sais pas comment le vérifier moi-même. Il y a aussi la question de savoir si toutes ces méthodes sont compatibles avec les différents navigateurs.

0 votes

Votre alerte dans IE est vide parce que ".text()" ne récupère pas tout le contenu de votre sous-arbre DOM. Essayez $(badgeFragment).html()

64voto

roosteronacid Points 9678

Avec jQuery 1.4, vous pouvez créer des éléments HTML comme suit :

// create an element with an object literal, defining properties
var e = $("<a />", {
    href: "#",
    "class": "a-class another-class", // you need to quote "class" since it's a reserved keyword
    title: "..."
});

// add the element to the body
$("body").append(e);

Voici un lien vers la documentation .

Je ne suis pas sûr que cette approche soit plus rapide que l'utilisation de la fonction html() de jQuery. Ou plus rapide que d'ignorer complètement jQuery et d'utiliser la fonction innerHTML sur un élément. Mais pour ce qui est de la lisibilité, l'approche jQuery est ma préférée. Et dans la plupart des cas, le gain de performance lié à l'utilisation de l'approche innerHTML est marginal.

1 votes

Vous avez oublié une virgule après le premier argument de jQuery ($).

1 votes

@roosteronacid en fonction de la Documents sur jQuery The name "class" must be quoted in the object since it is a JavaScript reserved word .

1 votes

@Peter yep. Cela vaut pour tous les mots réservés. J'ai mis à jour ma réponse.

11voto

Pointy Points 172438

Vous n'avez pas besoin d'appeler document.createElement :

$('#existingContainer').append(
  $('<div/>')
    .attr("id", "newDiv1")
    .addClass("newDiv purple bloated")
    .append("<span/>")
      .text("hello world")
);

Il existe toutes sortes d'outils utiles dans jQuery pour étendre/amender le DOM. Regardez les différentes méthodes "wrap" par exemple.

Autre possibilité : pour les gros blocs de nouveau contenu, il est préférable que votre serveur les prépare (en utilisant le système de templating côté serveur, quel qu'il soit) et les récupère avec $.load() ou une autre approche ajax.

8voto

lomaxx Points 32540

Je serais enclin à regarder l'un des moteurs de templating pour jquery comme jQote

1 votes

+1. ou jsRender, ou underscore - il y a beaucoup de choix, et ils sont bien meilleurs, notamment parce que Javscript ne supporte pas les chaînes de caractères multi-lignes et les fonctions de remplacement de paramètres de type sprintf.

8voto

Simon Points 4467

John Resig (créateur de jQuery) a suggéré d'utiliser cette méthode de modélisation en 2008. Elle présente en fait des caractéristiques assez intéressantes :

<script type="text/html" id="item_tmpl">

  <div id="<%=id%>" class="<%=(i % 2 == 1 ? " even" : "")%>">
    <div class="grid_1 alpha right">
      <img class="righted" src="<%=profile_image_url%>"/>
    </div>
    <div class="grid_6 omega contents">
      <p><b><a href="http://stackoverflow.com/<%=from_user%>"><%=from_user%></a>:</b> <%=text%></p>
    </div>
  </div>

</script>

puis le récupérer en utilisant...

var results = document.getElementById("results");
results.innerHTML = tmpl("item_tmpl", dataObject);

Voir ici pour tous les détails :
http://ejohn.org/blog/javascript-micro-templating/

0 votes

ICanHaz est très bien, @MarkAmery, mais il m'a fait perdre quelques heures avant que je ne comprenne que lui ou le modèle Mustache ne gèrent pas très bien certains caractères, comme la barre oblique inversée \ . Je ne peux pas me permettre cette perte de temps !

0 votes

@ErikE Ouch. Je suis assez surpris qu'une bibliothèque avec autant d'activité qu'icanhaz soit cassée de manière significative. Y a-t-il une chance que vous puissiez fournir un cas de démonstration minimal dans un jsfiddle ? Je pourrais y jouer et voir si je peux corriger le bug.

3voto

Skilldrick Points 33002

Je pense personnellement qu'il est plus important que le code soit lisible et modifiable que performant. Vous devez choisir celui que vous trouvez le plus facile à regarder et à modifier sans le casser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X