2012-11-02 26 views
9

Wiem, że wykonywanie wielu manipulacji w domenie jest złe, ponieważ wymusza wielokrotne odświeżanie."wirtualna" manipulacja domem?

tj:

$('body').append('<div />') 
     .append('<div />') 
     .append('<div />') 
     .append('<div />'); 

Zamiast lepszą praktyką jest podobno:

$('body').append('<div><div></div><div></div><div></div><div></div></div>'); 

ale jestem ciekaw wirtualnym manipulacji

tj:

$('<div />').append('<div />') 
      .append('<div />') 
      .append('<div />') 
      .append('<div />') 
      .appendTo('body'); 

jest to Nadal jest źle, oczywiście będzie kilka narzutów związanych z wywoływaniem funkcji kilka razy, ale czy będą jakieś poważne hity wydajności?


Powód pytam to:

var divs = [ 
    {text: 'First', id: 'div_1', style: 'background-color: #f00;'}, 
    {text: 'Second', id: 'div_2', style: 'background-color: #0f0;'}, 
    {text: 'Third', id: 'div_3', style: 'background-color: #00f;'}, 
    {text: 'Fourth', id: 'div_4', style: 'background-color: #f00;'}, 
    {text: 'Fifth', id: 'div_5', style: 'background-color: #0f0;'}, 
    {text: 'Sixth', id: 'div_6', style: 'background-color: #00f;'} 
]; 

var element = $('<div />'); 

$.each(divs, function(i,o){ 
    element.append($('<div />', o)); 
}); 

$('body').append(element); 

Wyobraźmy sobie, że tablica DIV ma pochodzić z tabeli bazy danych opisujących postać (ok, używam div w przykładzie, ale może być łatwo zastąpione przez wejścia) lub coś podobnego.

lub z „zalecanych” wersji mamy:

var divs = [ 
    {text: 'First', id: 'div_1', style: 'background-color: #f00;'}, 
    {text: 'Second', id: 'div_2', style: 'background-color: #0f0;'}, 
    {text: 'Third', id: 'div_3', style: 'background-color: #00f;'}, 
    {text: 'Fourth', id: 'div_4', style: 'background-color: #f00;'}, 
    {text: 'Fifth', id: 'div_5', style: 'background-color: #0f0;'}, 
    {text: 'Sixth', id: 'div_6', style: 'background-color: #00f;'} 
]; 

var element = '<div>'; 

$.each(divs, function(i,o){ 
    element += '<div '; 

    $.each(o, function(k,v){ 
     if(k != 'text'){ 
      element += k+'="'+v+'" '; 
     }    
    }); 

    element += '>'+o.text+'</div>'; 

}); 

element += '</div>'; 

$('body').append(element); 
+0

@nathan hayfield: "wydaje się, że jest nadal zły" - dlaczego tak jest? "dlaczego po prostu nie używać" - i dlaczego nie po prostu zachować go tak, jak jest? – zerkms

+0

@nathan hayfield: "znacznie szybciej" ??? Czy potrafisz powiedzieć różnicę ** REAL ** dla 5 'append' połączeń vs konkatenacji? Kod jest napisany dla ludzi i jest zoptymalizowany ** TYLKO ** nie spełnia wymagań dotyczących wydajności. – zerkms

+2

Repaints są prawdopodobnie odłożone do czasu zakończenia eventu, który już masz. – millimoose

Odpowiedz

9

Po pierwsze, mimo że jest wielki, aby przeczytać o potencjalnej wydajności uderza jak to zawsze należy zacząć od pomiaru, aby zobaczyć, jeśli nawet mają problem.

Jeśli nie możesz wykryć problemu, napisz najbardziej czytelny kod.

Jeśli możesz dostrzec problem, zmierzyć, zmienić i zmierzyć.

Powiedziawszy to wszystko, ostatni wysłany przez ciebie przykład zawiera elementy, które nie zostały jeszcze zapisane w DOM, więc nie będzie odświeżenia, dopóki appendTo nie doda elementów do DOM.

Byłbym bardzo zaskoczony, gdyby udało się uchwycić różnicę w prędkości między drugim a trzecim przykładem - i całkiem zdziwiony, gdybyś zauważył jakąkolwiek istotną różnicę między nimi.

+0

Ale nie ma nic złego w korzystaniu z podejścia fragmentu dokumentu jako najlepszej praktyki (jeśli to możliwe). –

+0

Dopóki nie powoduje to uszkodzenia czytelności. Dostawcy przeglądarek ciężko pracują nad tym, aby ich przeglądarki były ultraszybkie, więc naprawdę musisz się martwić, że Twój kod będzie łatwy do zrozumienia i zmiany. – Fenton

+0

Nie jestem pewien, jak duże są aplikacje, które piszesz. Ale piszę aplikacje na poziomie przedsiębiorstwa, które są świetnymi świnkami wydajnościowymi i chociaż nie nadążam za przedwczesną optymalizacją, zdecydowaliśmy się przyjąć wiele praktyk, o których wiemy, że są szybsze ... Kocham to, ale nie znoszę, że aplikacja jest powolna w IE jeszcze bardziej –

1

Jeśli naprawdę martwisz się o wydajność podczas dołączania węzłów, musisz użyć modułów dokumentu. Pozwalają one na dołączanie elementów do domingu bez odświeżania. John Resign ma numer excellent article na ten temat. Zauważa wzrost wydajności o 200-300%. Zaimplementowałem fragmenty dokumentów w jednej z moich aplikacji i mogę potwierdzić jego roszczenie.

+1

jQuery wewnętrznie używa fragmentów dokumentu, gdy robisz coś takiego jak '$ ("

")' –

+0

@Juan: Ah - tak to robi. Dzięki za wskazanie tego (przepraszam, pochodzę z waniliowego tła). –

+0

Należy zauważyć, że post został napisany 4 lata temu. Nagrywanie osi czasu w narzędziach programistycznych Chrome mówi mi, że jego strona testowa tylko raz wykonuje układ i malowanie. – millimoose

0

Myślę, że jeśli zaczniesz dochodzić do punktu, w którym ten rodzaj kodu jest wąskim gardłem wydajności, powinieneś używać szablonów zamiast manipulacji DOM.

Ale tak, użycie podejścia polegającego na fragmentacji dokumentu (umieszczenie wszystkich węzłów w odłączonym węźle przed dołączeniem do DOM) będzie w większości przypadków szybsze, prawie nigdy wolniejsze.

1

Cokolwiek stało się z dobrej starej generacji znaczników w czasie wykonywania? Poważnie, co się stało?

Zgadzam się z punktem @ Sohnee na temat znaczenia czytelności, ale manipulacje DOM są jednymi z najdroższych operacji, jakie może wykonać przeglądarka. Opcja utrzymywania ciągu znaczników może być doskonale czytelna i zapewniać poprawę w zakresie doświadczenia użytkownika, która jest nieistotna.

Tworzymy tabelę 10x100 w czasie wykonywania - całkiem rozsądny (i nie najbardziej złożony scenariusz) do dzielenia danych. Na czterordzeniowym komputerze z najnowszą wersją przeglądarki Chrome skrypt manipulacji DOM zajmuje 60 ms, w przeciwieństwie do 3ms dla buforowania znaczników.

To jest nieodróżnialna różnica w mojej konfiguracji, ale co z biednym chrząszczem liczbowym siedzącym za firmową zaporą ogniową i wciąż zmuszonym do używania przestarzałej wersji IE? Co się stanie, jeśli wymagane operacje DOM będą cięższe, z manipulacją atrybutami i agresywnym wymuszaniem ?

Wszystko, co powiem, to to, że jeśli chcesz zoptymalizować niektóre javascript, nie jest to złe miejsce na początek.

+0

AJAX się stało;) Jeśli martwisz się o słabych użytkowników IE, możesz również zaoferować wersję bez ajax'u, ale często generowanie znaczników javascript zapewnia o wiele bardziej przyjazny dla użytkownika interfejs, na przykład, powiedzmy, że masz '. dodaj jeszcze 10 przycisków atrybutów, które pokazały 10 dodatkowych wejść, na pewno możesz wygenerować 500 wejść na początek i po prostu pokazać/ukryć, lub możesz po prostu wygenerować 10 w locie, tak, jeśli ma sens generowanie znaczników w czasie wykonywania , ale są na to rzeczywiste przypadki użycia. – Hailwood

+0

@Hailwood: of_ಠ * oczywiście * ajax się stało! Kiedy mówiłem o generowaniu marży podczas uruchamiania, założyłem, że było jasne, że zasugerowano, aby być * na kliencie * - tj. Przekształcając dane JSON w ciąg html najpierw i tylko wtedy, gdy został dodany do DOM –

+0

Cóż, w takim przypadku tak naprawdę jest to tylko kwestia czytelności, która i jQuery uczyniła nas leniwymi, łatwiej jest pozwolić jQuery obsługiwać budowanie, niż robić to sami, ale w kwestii czytelności i "generowania marż w czasie wykonywania" właśnie to jest ostatnim przykładem w moim pytaniu, ale spójrz na powyższy przykład, w jaki sposób uczynisz je tak samo czytelnymi? – Hailwood