2009-05-25 11 views
32

Ho appena scritto una funzione $(). Bind ('evento') e mi sono preoccupato che questo tipo di chiamata potrebbe essere molto costoso se jQuery deve scorrere attraverso ogni elemento nel DOM per associare questo evento.Gli eventi vincolanti in jQuery sono molto costosi o molto economici?

O forse, è quasi efficiente come potrebbe essere un evento. I documenti jQuery che ho letto non lo chiariscono. Qualche opinione?

risposta

71

Esistono due elementi che possono rallentare il codice di associazione degli eventi: il selettore e il numero di associazioni. Il più critico dei due è il numero di associazioni, ma il selettore potrebbe influire sulle prestazioni iniziali.

Per quanto riguarda i selettori, assicurati di non utilizzare selettori di nomi di classe puri come .myclass. Se sai che la classe di myclass sarà sempre in un elemento <div>, fai in modo che il tuo selettore sia div.myclass in quanto aiuterà jQuery a trovare più rapidamente gli elementi corrispondenti. Inoltre, non approfittare di jQuery per darti enormi stringhe di selezione. Tutto ciò che può fare con i selettori di stringhe può anche farlo attraverso le funzioni, e questo è intenzionale, poiché è (marginalmente, ammettiamolo) più veloce farlo in questo modo poiché jQuery non deve sedersi intorno per analizzare la stringa per capire cosa tu vuoi. Quindi invece di fare $('#myform input:eq(2)'); potresti fare $('input','#myform').eq(2);. Specificando un contesto, non stiamo facendo l'aspetto di jQuery ovunque non sia necessario, il che è molto più veloce. More on this here.

Per quanto riguarda la quantità di associazioni: se si dispone di una quantità di elementi di dimensioni relativamente medie, si dovrebbe andare bene - qualsiasi cosa fino a 200, 300 potenziali combinazioni di elementi funzioneranno correttamente nei browser moderni. Se ne hai più di questo, potresti voler esaminare la Delegazione degli eventi.

Che cos'è la Delega eventi? In sostanza, quando si esegue il codice come questo:

$('div.test').click(function() { 
    doSomething($(this)); 
}); 

jQuery sta facendo qualcosa di simile dietro le quinte (vincolante un evento per ogni elemento abbinati):

$('div.test').each(function() { 
    this.addEventListener('click', function() { 
     doSomething(this); 
    }, false); 
}); 

Questo può ottenere inefficiente se si dispone di un grande quantità di elementi. Con la delega degli eventi, è possibile ridurre la quantità di associazioni effettuate fino a uno. Ma come? L'oggetto evento ha una proprietà target che ti consente di sapere su quale elemento ha agito l'evento. Così si potrebbe poi fare qualcosa di simile:

$(document).click(function(e) { 
    var $target = $(e.target); 
    if($target.is('div.test')) { // the element clicked on is a DIV 
           // with a class of test 
     doSomething($target); 
    } 
}); 

Per fortuna che in realtà non hanno al codice di cui sopra con jQuery. La funzione live, che è pubblicizzata come un modo semplice per associare eventi a elementi che non esistono ancora, è in realtà in grado di farlo utilizzando la delega degli eventi e controllando al momento in cui un'azione si verifica se la destinazione corrisponde al selettore specificato . Questo ha l'effetto collaterale, ovviamente, di essere molto utile quando la velocità è importante.

La morale della storia?Se sei preoccupato per la quantità di binding il tuo script ha appena sostituito .bind con .live e assicurati di avere selettori intelligenti.

Notare, tuttavia, che non tutti gli eventi sono supportati da .live. Se hai bisogno di qualcosa che non è supportato da esso, è possibile controllare il plugin livequery, che è in diretta su steroidi.

+1

questa è una grande risposta – Jason

+2

Va notato che poiché 'delegato' è stato aggiunto, è possibile che gli script siano ancora più veloci di quanto fossero con' live'. –

+4

Ho trovato che .myClass è più veloce di div.myClass: http://jsperf.com/div-test-vs-test –

-1

Fondamentalmente, non hai intenzione di fare di meglio. Tutto ciò che sta facendo è chiamare attachEventListener() su ciascuno degli elementi selezionati.

In fase di analisi da solo, questo metodo è probabilmente più veloce di impostare gestori di eventi inline su ciascun elemento.

In generale, considererei un'operazione molto economica.

Problemi correlati