2010-05-11 4 views
2

Je souhaite utiliser document.createDocumentFragment() pour créer une collection optimisée d'éléments HTML contenant ".data" provenant de jQuery (v 1.4.2), mais je suis sorte de coincé sur la façon de faire ressortir les données à partir des éléments HTML.Utilisation de document.createDocumentFragment() éléments enfant dom contenant jQuery.data

Voici mon code:


var genres_html = document.createDocumentFragment(); 
$(xmlData).find('genres').each(function(i, node) { 
    var genre = document.createElement('a'); 
    $(genre).addClass('button') 
     .attr('href', 'javascript:void(0)') 
     .html($(node).find('genreName:first').text()) 
     .data('genreData', { id: $(node).find('genreID:first').text() }); 
    genres_html.appendChild(genre.cloneNode(true)); 
}); 

$('#list').html(genres_html); 

// error: $('#list a:first').data('genreData') is null 
alert($('#list a:first').data('genreData').id); 

ce que je fais mal ici? Je suspecte que c'est probablement quelque chose avec .cloneNode() ne reportant pas les données quand l'élément est ajouté au documentFragment. Parfois, il y a des tonnes de lignes donc je veux garder les choses assez optimisées, en vitesse.

Merci!

Répondre

1

Vous exécutez cloneNode sur un objet jQuery. Vous démarrez avec une API native, puis convertissez-la en objet jQuery, puis revenez en arrière.

Je suppose que vous pourriez faire:

genres_html.appendChild(genre.get(0).cloneNode(true)); 

Mais alors je soupçonne que vous perdriez votre data.


EDIT:

Si vous voulez jQuery, au lieu de créer un fragment, essayez de créer un objet jQuery vide, poussant chaque genre en elle:

var genres_html = $(); 
... 
genres_html.push(genre); 

EDIT:

Essayez-le. Je ne suis pas un expert du DOM, mais ça peut marcher pour vous.

var genres_html = document.createDocumentFragment(); 
$(xmlData).find('genres').each(function(i, node) { 
    var genre = document.createElement('a'); 
    genre.setAttribute('class','button'); 
    genre.setAttribute('href', 'javascript:void(0)'); 
    var $node = $(node); 
    genre.setAttribute('genreData', $node.find('genreID:first').text()); 
    genre.innerHTML = $node.find('genreName:first').text(); 
    genres_html.appendChild(genre.cloneNode(true)); // Not sure why you would need to make a clone?? 
}); 

var list = document.getElementById('list'); 
list.appendChild(genres_html); 

// error: $('#list a:first').data('genreData') is null 
alert($('#list a:first').attr('genreData')); 

Faites-moi savoir si cela fonctionne.

EDIT: Changé mon erreur avec innerHTML

EDIT2: Utilisation innerHTML native pour ajouter à #list

+0

Oui, je pense que c'est la partie principale avec laquelle je suis confus, je ne sais pas si je veux commencer avec un objet jQuery ou non. Je regardais cette diapositive, mais c'est en JS: http://ejohn.org/apps/workshop/adv-talk/#6 - ce dont j'ai besoin c'est de le convertir en un objet jQuery qui contient les données de l'élément . – taber

+0

Vous pouvez utiliser les fonctions natives 'setAttribute' et' innerHTML', mais si vous avez besoin d'utiliser 'data()' de jQuery, vous aurez évidemment besoin d'un objet jQuery. Donc la question est, * avez-vous vraiment besoin d'utiliser 'data' *? Peut-être que vous pourriez vous débrouiller avec la définition d'un attribut personnalisé. Je mettrai à jour ma réponse avec une possibilité. – user113716

+0

Merci, ouais le problème est que je ne peux pas ajouter un documentElement "jQuerified" (qui contient les données) à mon documentFragment. Oui, je voudrais utiliser «données». :( – taber

1

Désolé je ne suis pas très clair - je veux le gain de performance de l'utilisation documentFragments mais la "propreté" de jQuery. :) Génial, je pense que je l'ai compris!


var genres_list = document.createDocumentFragment(); 
$(xmlData).find("genres").each(function(i, node) { 
    genres_list.appendChild(
     $('<a></a>').addClass('button') 
      .attr('href', 'javascript:void(0)') 
      .html('Anchor Text Here') 
      .data('genreData', {id: 2000}) 
      .get(0) // ah-ha! 
     ) 
    ); 
}); 

$('#list').append(genres_list); 

// alerts 2000 
alert($('#list').find('a:first').data('genreData').id); 

Merci beaucoup pour votre aide! Je pense que le problème était le .get (0) manquant en l'ajoutant au documentFragment. Il ressemble à .get (0) retourne également les données intactes!

Les gains de performance sont toujours à déterminer. Je sais que jQuery 1.4 utilise documentFragments mais ne sait pas exactement où/quelles méthodes. Au moins, cela fonctionne maintenant! :)

+1

Si vous recherchez des gains de performances, vous devez d'abord ignorer la création d'un objet jQuery, ainsi que l'API de jQuery. Tout cela est juste une abstraction de l'API native, et ne fera que ralentir votre code. Si la performance est acceptable, alors aussi bien utiliser jQuery. Si vous avez besoin d'améliorations, alors allez natif. Utiliser un 'documentFragment' ne servira probablement pas à remplir un objet jQuery vide car jQuery ne créera probablement que son propre fragment. – user113716

+1

Bon point! Ditching jQuery à ce stade est hors de question cependant. : DI met en place un test rapide de référence concenant les nombres 0-1000 à la lettre 'h' et les ajoutant à un div ... 1) en utilisant ma méthode ci-dessus (jQuery avec document.createDocumentFragment), 2) en utilisant jQuery.append dans chaque itération de la boucle for, et 3) en utilisant document.createDocumentFragment sans jQuery. Voici un échantillon des résultats: 1) 922ms, 2) 1547ms, 3) 828ms. Donc, pour ~ 600 ms d'économies, je vais avec la première option. : D Merci pour la nouvelle syntaxe de création de documentElement! 1.4 est une bonne chose. – taber

Questions connexes