2 votes

En utilisant document.createDocumentFragment() des éléments du DOM enfants contenant jQuery.data

Je veux 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 un peu bloqué sur la façon de faire remonter les données des éléments HTML.

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);

// erreur: $('#list a:first').data('genreData') est nul
alert($('#list a:first').data('genreData').id);

Qu'est-ce que je fais de mal ici? Je soupçonne que c'est probablement quelque chose avec .cloneNode() qui ne transfère pas les données lorsque 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 termes de vitesse.

Merci!

1voto

user113716 Points 143363

Vous exécutez cloneNode sur un objet jQuery. Vous commencez avec l'API native, puis le convertissez en un 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 vos data.


EDIT:

Si vous voulez du jQuery, au lieu de créer un fragment, essayez de créer un objet jQuery vide, puis d'y pousser chaque genre:

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

EDIT:

Essayez ceci. Je ne suis pas un expert en DOM, mais cela peut fonctionner 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) );   // Pas sûr pourquoi vous auriez besoin de faire un clone??
});

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

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

Dites-moi si cela fonctionne.

EDIT: J'ai corrigé mon erreur avec innerHTML

EDIT2: Utilisation de innerHTML native pour ajouter à #list

1voto

taber Points 1463

Désolé, je n'étais pas très clair - je veux le gain de performance de l'utilisation de documentFragments mais la "propreté" de jQuery. :) C'est super cependant, je pense avoir compris !

var genres_list = document.createDocumentFragment();
$(xmlData).find("genres").each(function(i, node) {
    genres_list.appendChild(
        $('').addClass('button')
            .attr('href', 'javascript:void(0)')
            .html('Texte de l'ancre ici')
            .data('genreData', {id: 2000})
            .get(0) // ah-ha!
        )
    );
});

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

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

Un grand merci pour votre aide ! Je pense que le problème était l'absence de .get(0) lors de l'ajout au documentFragment. Il semble que .get(0) renvoie également les données intactes !

Les gains de performances sont toujours à déterminer. Je sais que jQuery 1.4 utilise des documentFragments mais je ne suis pas exactement sûr où/quelles méthodes. Au moins ça fonctionne maintenant! :)

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