2009-05-25 8 views
32

Ich schrieb gerade eine $(). Bind ('event') Funktion und dann wurde besorgt, dass diese Art eines Aufrufs sehr teuer sein könnte, wenn jQuery jedes Element im DOM durchlaufen muss, um dieses Ereignis zu binden.Sind verbindliche Ereignisse in jQuery sehr teuer oder sehr kostengünstig?

Oder vielleicht ist es ungefähr so ​​effizient wie eine Veranstaltung sein könnte. Die jQuery-Dokumente, die ich gelesen habe, machen das nicht klar. Irgendwelche Meinungen?

Antwort

71

Es gibt zwei Dinge, die Ihren Ereignisbindungscode langsam machen können: den Selektor und die Anzahl der Bindungen. Die kritischste der beiden ist die Anzahl der Bindungen, aber der Selektor kann sich auf die anfängliche Leistung auswirken.

Soweit Selektoren gehen, nur sicherstellen, dass Sie nicht reine Klassennamen Selektoren wie .myclass verwenden. Wenn Sie wissen, dass die Klasse immer in einem <div> Element sein wird, stellen Sie Ihren Selektor auf div.myclass, da dies dazu beiträgt, dass jQuery die übereinstimmenden Elemente schneller findet. Nimm auch keinen Vorteil von jQuery, indem du ihm riesige Selektorketten gibst. Alles, was es mit String-Selektoren tun kann, kann es auch durch Funktionen tun, und dies ist beabsichtigt, da es (marginal, zugegebenermaßen) schneller ist, es auf diese Weise zu tun, da jQuery nicht herumsitzen muss, um die Zeichenfolge zu analysieren, um herauszufinden, was Sie wollen. Anstatt also $('#myform input:eq(2)'); zu tun, könnten Sie $('input','#myform').eq(2); tun. Indem wir einen Kontext angeben, lassen wir jQuery auch nicht überall aussehen, wo es nicht viel schneller ist. More on this here.

Soweit die Anzahl der Bindungen: Wenn Sie eine relativ große Anzahl von Elementen haben, dann sollten Sie in Ordnung sein - alles bis zu 200, 300 mögliche Element Matches werden in modernen Browsern gut funktionieren. Wenn Sie mehr als das haben, sollten Sie stattdessen in Event Delegation suchen.

Was ist Ereignisdelegation? Im Wesentlichen, wenn Sie laufen Code wie folgt:

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

jQuery ist hinter den Kulissen so etwas wie dies zu tun (ein Ereignis für jedes verglichene Element-Bindung):

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

Dies kann ineffizient, wenn man eine haben große Anzahl von Elementen. Mit der Ereignisdelegierung können Sie die Anzahl der vorgenommenen Bindungen auf eine reduzieren. Aber wie? Das Ereignisobjekt verfügt über eine target-Eigenschaft, mit der Sie wissen, auf welches Element das Ereignis reagiert hat. So könnte man dann so etwas tun:

$(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); 
    } 
}); 

Zum Glück müssen Sie nicht tatsächlich die oben mit jQuery-Code. Die live-Funktion, die als eine einfache Möglichkeit zum Binden von Ereignissen an noch nicht vorhandene Elemente angekündigt wird, ist tatsächlich in der Lage, dies zu tun, indem Ereignisdelegierung und -überprüfung durchgeführt werden, wenn das Ziel mit dem von Ihnen angegebenen Selektor übereinstimmt . Dies hat natürlich den Nebeneffekt, dass es sehr praktisch ist, wenn Geschwindigkeit wichtig ist.

Die Moral der Geschichte?Wenn Sie Bedenken hinsichtlich der Anzahl der Bindungen haben, die Ihr Skript gerade ersetzt hat, geben Sie .bind mit .live ein und stellen Sie sicher, dass Sie über intelligente Selektoren verfügen. Bitte beachten Sie, dass nicht alle Ereignisse von .live unterstützt werden. Wenn Sie etwas brauchen, das nicht von ihm unterstützt wird, können Sie das livequery Plugin, das auf Steroiden live ist, ausprobieren.

+1

das ist eine gute Antwort – Jason

+2

Es sollte angemerkt werden, dass seit "Delegate" hinzugefügt wurde, ist es möglich, dass Ihre Skripte noch schneller als bei 'live' sind. –

+4

Ich habe festgestellt, dass .myClass schneller ist als div.myClass: http://jsperf.com/div-test-vs-test –

-1

Im Grunde werden Sie nicht besser machen. Es wird lediglich attachEventListener() für jedes ausgewählte Element aufgerufen.

Bei der Parse-Zeit ist diese Methode wahrscheinlich schneller als das Setzen von inline-Event-Handlern für jedes Element.

Im Allgemeinen würde ich dies als eine sehr kostengünstige Operation betrachten.

Verwandte Themen