Jaki jest najskuteczniejszy sposób tworzenia elementów HTML za pomocą jQuery?


425

Ostatnio robiłem wiele modalnych okien pop-up i co nie, do czego użyłem jQuery. Metoda, której użyłem do utworzenia nowych elementów na stronie, była w przeważającej mierze następująca:

$("<div></div>");

Mam jednak wrażenie, że nie jest to najlepsza ani najwydajniejsza metoda tego. Jaki jest najlepszy sposób tworzenia elementów w jQuery z perspektywy wydajności?

Ta odpowiedź zawiera punkty odniesienia do poniższych sugestii.


1
Eksperymentuj też z usuwaniem stylów i sprawdź, czy to przyspieszy. Uważam, że aplikacja CSS i aktualizacje najbardziej spowalniają pracę na dużych stronach.
— CVertex

3
Uważaj na przedwczesną optymalizację - jeśli nie robisz tego jednocześnie dla setek elementów DOM lub używasz BARDZO starych przeglądarek, prawdopodobnie nie zauważysz żadnej różnicy w wydajności przeglądarki.
— Blazemonger

1
@Blazemonger Nie tyle potrzebowałem bardziej wydajnej metody tworzenia elementów DOM, ale sytuacja, w której się znalazłem, sprawiła, że ​​zastanowiłem się, jakie są alternatywy i jak wydajne mogą być.
— Darko Z

2
jQuery jest biblioteką - z tego powodu prawie zawsze ponosisz ogólne koszty wydajności: to tak, jakbyś rozmawiał z kimś przez tłumacza. O ile nie chcesz używać nieprzetworzonego JavaScript, skorzystaj z tego, jak szybko jest napisać $ („<div>”) i zaakceptować spadek wydajności.
— Danny Bullis,

1
jsben.ch/#/bgvCV <= ten test porównawczy powinien odpowiedzieć na twoje pytanie
— EscapeNetscape

Odpowiedzi:


307

Używam $(document.createElement('div')); testów porównawczych pokazuje, że ta technika jest najszybsza. Spekuluję, że dzieje się tak, ponieważ jQuery nie musi identyfikować go jako elementu i sam tworzyć elementu.

Powinieneś naprawdę przeprowadzić testy porównawcze z różnymi silnikami Javascript i zważyć wyniki swoich odbiorców. Podejmij decyzję stamtąd.


16
jQuery „dołącza” go do DOM? Gdzie? To nie ma dla mnie większego sensu - dokąd poszedłby div?
— strager

28
utworzony div w jquery musi być dodany tak jak w javascript. $ („<div>”) sam w sobie nie jest dołączony do DOM, dopóki go nie dołączysz () do czegoś.
— Owen,

6
@David - oczywiście masz rację. Zauważę, że dodałem komentarz około 2 lata temu, kiedy zaczynałem się uczyć jQuery. Musisz zrobić appendTo... Ponieważ komentarze były oczywiście błędne, usunąłem je.
— tvanfosson

16
Odniesienie do testów porównawczych jest świetne, ale testuje także tworzenie dziesiątek tysięcy elementów. Kiedy NIGDY nie będziesz mieć do czynienia z tyloma elementami w typowej sytuacji? Możliwe, że masz większe zmartwienia niż jak stworzyć element. document.createElement „Przebiegł 39 682 razy w 0,097 sekundy”, podczas gdy $ („<div>”) „Przebiegł 12 642 w 0,068 sekundy.” Powiedziałbym, że jeśli coś może uruchomić tysiące razy w mniej niż sekundę, jesteś bezpieczny.
— Danny Bullis,

20
Ponadto za pomocą $ (document.createElement ('div')); Powiedziałbym, że jest mniej wydajny, ponieważ pisanie zajmuje znacznie więcej korzyści, które otrzymasz w przeglądarce, jeśli tworzysz tylko jeden element tu i tam. Technicznie samo jQuery jest mniej wydajne jak biblioteka ze względu na koszty wyszukiwania i narzut związany z korzystaniem z niego. Jeśli ktoś tak bardzo chce zaoszczędzić cenne tysięczne sekundy, używając document.createElement zamiast $ ('<div>'), to nie powinien używać jQuery:], ponieważ $ ('<div>') jest jednym z powodów, dla których go używasz!
— Danny Bullis,

163

osobiście sugerowałbym (dla czytelności):

$('<div>');

niektóre liczby dotyczące dotychczasowych sugestii (safari 3.2.1 / mac os x):

var it = 50000;

var start = new Date().getTime();
for (i = 0; i < it; ++i)  {
  // test creation of an element 
  // see below statements
}
var end = new Date().getTime();
alert( end - start );                

var e = $( document.createElement('div') );  // ~300ms
var e = $('<div>');                          // ~3100ms
var e = $('<div></div>');                    // ~3200ms
var e = $('<div/>');                         // ~3500ms              

15
Z dokumentacji jquery: „Podczas tworzenia pojedynczych elementów użyj tagu zamykającego lub formatu XHTML. Na przykład, aby utworzyć zakres, użyj $ („<span />”) lub $ („<span> </span>”) zamiast bez zamykającego ukośnika / znacznika. '
— tvanfosson

6
@ Poza tym takie zachowanie jest błędem, a nie cechą. Kosz na śmieci, śmieci na śmieci - tak się składa, że ​​śmieci, które dostajesz, są do przyjęcia. Nie polegaj na tym między wersjami jQuery, chyba że zmieni się specyfikacja funkcji.
— strager

2
Zgodnie z oczekiwaniami, podobne liczby w Mac OS X Chrome (100 ms dla createElement () vs. 500 ms parsowanie tekstu) i Mac OS X Firefox (350 ms vs. 1000 ms). Dzięki za napisanie pętli testowej.
— Annika Backstrom

3
@tvanfosson To się zmieniło, w obecnych dokumentach mówi: „Gdy parametr ma pojedynczy znacznik (z opcjonalnym znacznikiem zamykającym lub szybkim zamykaniem) - $ („ <img /> ”) lub $ („ <img> ” ), $ („<a> </a>”) lub $ („<a>”) - jQuery tworzy element za pomocą natywnej funkcji JavaScript createElement (). ”
— metatron

3
@MarcStober Bez przestępstwa. Nadal jest tutaj: http://api.jquery.com/jQuery/#jQuery2 . Dokumenty wspominają o opcjonalnym tagu zamykającym lub szybkim zamykaniu
— metatron

155

Pytanie:

Jaki jest najskuteczniejszy sposób tworzenia elementów HTML za pomocą jQuery?

Odpowiedź:

Ponieważ chodzi o jQueryto, myślę, że lepiej jest zastosować to (czyste) podejście (używasz)

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'text':'Text Only',
}).on('click', function(){
    alert(this.id); // myDiv
}).appendTo('body');

PRÓBNY.

W ten sposób można nawet używać procedur obsługi zdarzeń dla określonego elementu, takiego jak

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'style':'cursor:pointer;font-weight:bold;',
    'html':'<span>For HTML</span>',
    'click':function(){ alert(this.id) },
    'mouseenter':function(){ $(this).css('color', 'red'); },
    'mouseleave':function(){ $(this).css('color', 'black'); }
}).appendTo('body');

PRÓBNY.

Ale gdy masz do czynienia z wieloma elementami dynamicznymi, powinieneś unikać dodawania zdarzenia handlersdo konkretnego elementu, zamiast tego powinieneś użyć delegowanego modułu obsługi zdarzeń, takiego jak

$(document).on('click', '.myClass', function(){
    alert(this.innerHTML);
});

var i=1;
for(;i<=200;i++){
    $('<div/>', {
        'class':'myClass',
        'html':'<span>Element'+i+'</span>'
    }).appendTo('body');
}

PRÓBNY.

Tak więc, jeśli utworzysz i dodasz setki elementów o tej samej klasie, tj. ( myClass), Wówczas zajmie się mniej pamięci do obsługi zdarzeń, ponieważ tylko jeden moduł obsługi będzie mógł wykonać zadanie dla wszystkich dynamicznie wstawianych elementów.

Aktualizacja: Ponieważ możemy użyć następującego podejścia do utworzenia elementu dynamicznego

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    'size': '30'
}).appendTo("body");

Ale tego sizeatrybutu nie można ustawić za pomocą tego podejścia za pomocą jQuery-1.8.0lub później, a oto stary raport o błędach , spójrz ten przykład za pomocą, jQuery-1.7.2który pokazuje, że sizeatrybut jest ustawiony na 30powyższy przykład, ale za pomocą tego samego podejścia, którego nie możemy ustawić sizeza pomocą atrybutu jQuery-1.8.3, tutaj to niedziałające skrzypce . Aby ustawić sizeatrybut, możemy zastosować następujące podejście

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    attr: { size: "30" }
}).appendTo("body");

Albo ten

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    prop: { size: "30" }
}).appendTo("body");

Możemy przekazać attr/propjako obiekt podrzędny, ale to działa w jQuery-1.8.0 and laterwersjach sprawdzić ten przykład , ale to nie będzie działać w jQuery-1.7.2 or earlier(nie testowane we wszystkich wcześniejszych wersjach).

BTW, wzięte z jQueryraportu o błędzie

Istnieje kilka rozwiązań. Po pierwsze, wcale go nie używaj, ponieważ nie oszczędza to miejsca, a to poprawia przejrzystość kodu:

Zalecili stosowanie następującego podejścia ( działa również we wcześniejszych , przetestowano w 1.6.4)

$('<input/>')
.attr( { type:'text', size:50, autofocus:1 } )
.val("Some text").appendTo("body");

Lepiej więc zastosować to podejście, IMO. Ta aktualizacja jest wykonywana po przeczytaniu / znalezieniu tej odpowiedzi, a ta odpowiedź pokazuje, że jeśli używasz'Size'(capital S) zamiast 'size'niej, będzie ona działać dobrze , nawet wversion-2.0.2

$('<input>', {
    'type' : 'text',
    'Size' : '50', // size won't work
    'autofocus' : 'true'
}).appendTo('body');

Przeczytaj także o rekwizytach , ponieważ istnieje różnica,Attributes vs. Properties różni się w zależności od wersji.


Co to za sintax to $ ('<div />', {.........}), szukałem go i znalazłem podobne za pomocą $ ('<div>) .attr ( {......})?
— Rafael Ruiz Tabares

@RafaelRuizTabares, w $('<div>', {...})którym mijasz obiekt, który zawiera wszystkie atrybuty, i $('<div>').attr({...})tworzysz element bez żadnych atrybutów, ale ustawiasz atrybuty za pomocą attr()metody później.
— Alfa

@ TheAlpha gdzie mogę znaleźć informacje o tym, co mogę napisać w środku {}? Ponieważ widzę, że są to atrybuty i zdarzenia, ale dla <div> też używasz html. Dzięki!
— Rafael Ruiz Tabares

Przeszukaj jQuery.comstronę internetową może być pomocna @RafaelRuizTabares lub google :-)
— The Alpha

2
To zdecydowanie najczystszy i bardziej czytelny sposób! Prawdopodobnie nie jest to szybki sposób, ale z pewnością mniej podatny na błędy dodawania łańcucha. Dzięki @TheAlpha
— Ares

37

W rzeczywistości, jeśli robisz $('<div>'), jQuery również będzie używaćdocument.createElement() .

(Spójrz tylko na linię 117 ).

Istnieje pewien narzut wywołania funkcji, ale o ile wydajność nie jest krytyczna (tworzysz setki [tysięcy] elementów), nie ma większego powodu, aby powracać do zwykłego DOM .

Po prostu tworzenie elementów dla nowej strony internetowej jest prawdopodobnie przypadkiem, w którym najlepiej trzymać się jQuery sposobu robienia rzeczy.


20

Jeśli masz dużo treści HTML (więcej niż tylko jeden div), możesz rozważyć wbudowanie HTML w stronę w ukrytym pojemniku, a następnie zaktualizowanie go i udostępnienie w razie potrzeby. W ten sposób duża część znaczników może zostać wstępnie przeanalizowana przez przeglądarkę i uniknąć zakłócania się przez JavaScript po wywołaniu. Mam nadzieję że to pomoże!


Dzięki za radę. Użyłem tego podejścia wcześniej, jednak w tym konkretnym przypadku chciałbym się dowiedzieć o tworzeniu elementów.
— Darko Z

20

To nie jest poprawna odpowiedź na pytanie, ale nadal chciałbym się tym podzielić ...

Używanie tylko document.createElement('div')i pomijanie JQuery znacznie poprawi wydajność, jeśli chcesz tworzyć wiele elementów w locie i dołączać do DOM.


16

Myślę, że używasz najlepszej metody, ale możesz ją zoptymalizować, aby:

 $("<div/>");

11

Nie potrzebujesz surowej wydajności z operacji, którą wykonujesz niezwykle rzadko z punktu widzenia procesora.


Zależy od tego, jak często to robisz.
— Rich Bradshaw

8
OP tworzy modalne okienko wyskakujące . Ta operacja nie jest powtarzana tysiące razy na sekundę. Zamiast tego powtarza się to maksymalnie raz na kilka sekund. Korzystanie z tej jQuery(html :: String)metody jest całkowicie w porządku. Chyba że sytuacja jest bardzo nietypowe, jeden będzie mało prawdopodobne, aby osiągnąć lepsze postrzeganie wydajność. Wydaj energię optymalizacyjną na skrzynki, które mogłyby z niej skorzystać. Ponadto jQuery jest zoptymalizowany pod kątem prędkości na wiele sposobów. Rób z nim zdrowe rzeczy i zaufaj, ale sprawdź, czy jest szybki.
— yfeldblum

9

Musisz zrozumieć, że znaczenie wydajności tworzenia elementów nie ma znaczenia w kontekście używania jQuery.

Pamiętaj, że nie ma prawdziwego celu tworzenia elementu, chyba że faktycznie go użyjesz.

Możesz pokusić się o przetestowanie wydajności czegoś takiego jak $(document.createElement('div'))vs. $('<div>')i uzyskać duży wzrost wydajności dzięki użyciu, $(document.createElement('div'))ale to tylko element, którego jeszcze nie ma w DOM.

Jednak pod koniec dnia i tak będziesz chciał użyć tego elementu, więc prawdziwy test powinien obejmować np. .dołączyć do();

Zobaczmy, jeśli przetestujesz między sobą następujące elementy:

var e = $(document.createElement('div')).appendTo('#target');
var e = $('<div>').appendTo('#target');
var e = $('<div></div>').appendTo('#target');
var e = $('<div/>').appendTo('#target');

Zauważysz, że wyniki będą się różnić. Czasami jeden sposób jest lepszy od drugiego. A to tylko dlatego, że liczba zadań w tle na komputerze zmienia się z czasem.

Sprawdź się tutaj

Tak więc pod koniec dnia chcesz wybrać najmniejszy i najbardziej czytelny sposób tworzenia elementu. W ten sposób przynajmniej Twoje pliki skryptowe będą najmniejsze. Prawdopodobnie bardziej znaczący czynnik na punkcie wydajności niż sposób tworzenia elementu przed użyciem go w DOM.


Wiem, że to stare, ale nie ma potrzeby korzystania z jQuery w pierwszym przykładzie:document.getElementById('target).appendChild(document.createElement('div'));
— hisdrewness


7

Jednym z punktów jest to, że może być łatwiej zrobić:

$("<div class=foo id=bar style='color:white;bgcolor:blue;font-size:12pt'></div>")

Następnie wykonaj to wszystko za pomocą wywołań jquery.


3

Korzystam z jquery.min v2.0.3. Lepiej jest dla mnie użyć następujących:

var select = jQuery("#selecter");
jQuery("`<option/>`",{value: someValue, text: someText}).appendTo(select);

jak następuje:

var select = jQuery("#selecter");
jQuery(document.createElement('option')).prop({value: someValue, text: someText}).appendTo(select);

Czas przetwarzania pierwszego kodu jest znacznie krótszy niż drugiego kodu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.