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.

Darko Z
źródło
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.

strager
źródło
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              
piekarnik
źródło
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.

Alfa
źródło
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.

edwin
źródło
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!

Collin Allen
źródło
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.

Irshad
źródło
16

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

 $("<div/>");
tvanfosson
źródło
11

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

yfeldblum
źródło
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.

Jani Hyytiäinen
źródło
Wiem, że to stare, ale nie ma potrzeby korzystania z jQuery w pierwszym przykładzie:document.getElementById('target).appendChild(document.createElement('div'));
hisdrewness
8

Ktoś już dokonał testu porównawczego: jQuery document.createElement?

$(document.createElement('div')) jest wielkim zwycięzcą.

Erel Segal-Halevi
źródło
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.

Tobiasz
źródło
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.

Marcel GJS
źródło