5

jQueryのパフォーマンスをよりよく理解するために、次の質問に出くわしました。クリックイベントをリスト内のアイテムにバインドするための2つのほぼ等しいソリューションを検討してください。

リストアイテム:

<div id="items">
    <div class="item"><a href="#">One</a></div>
    <div class="item"><a href="#">Two</a></div>
    <div class="item"><a href="#">Three</a></div>
</div>

<div id="items2">
    <div class="item"><a href="#">One</a></div>
    <div class="item"><a href="#">Two</a></div>
    <div class="item"><a href="#">Three</a></div>
</div>

ID以外に2つのIDリストがあることに注意してください。ここで、次のjQueryを検討して、items内の各アンカーのクライアントイベントをバインドします。

$('#items').on('click', '.item a', function(e) {
   console.log("### Items click"); 
});

$('#items2 .item a').on('click', function(e) {
    console.log("### Items2 click");
});

これにより、リスト内のアイテムをクリックするとそれぞれのメッセージが出力されるという同じ結果が得られます。

バインドされているイベントを監視すると、最初のケースでは、クリックイベントが#itemsコンテナにバインドされており、子にバインドされているイベントはありません。ただし、2番目のケースでは、クリックイベントは親にバインドされていません#items2が、子要素のそれぞれにクリックイベントがあります。

さて、私の質問は次のとおりです。一方が他方よりも明らかに好ましいのでしょうか。ナイーブなので、最初のケースが望ましいと思いますが、jQueryの内部に関する知識が不足しているため、この2つは内部的には同等である可能性が非常に高くなります。

2つのケースを示すためにフィドルを用意しました。jQueryが要素に対して構築したイベントを観察することで、上記の仮定を導き出しました(Webブラウザーのコンソールで出力を確認できます)。

4

2 に答える 2

8

膨大な数の要素を扱っているのでない限り、どちらの方法でも問題はないでしょう。問題は、いつより効率的にする必要があるかということです。バインド時とトリガー時のどちらですか。

免責事項:私はこれらのテストのいずれかが完璧であるとは主張しません。また、私はChromeでのみテストしました。

結合時間

答えがわからなかったので、すべてを試してみることにしました。まず、委任を使用すると、バインドがはるかに高速になると想定しました(X回ではなく、1回だけバインドする必要があります)。これは正しいようです。

http://jsperf.com/on-delegate-vs-not-bind-only

委任しないでください: 100%遅くなります

トリガー時間

次に、イベントのトリガーをチェックするためにDOMの移動が必要ないため、委任を使用しない方が実際にはイベントをトリガーする方が速い可能性があると考えました。何らかの理由で、私はそれについて間違っていました:

http://jsperf.com/on-delegate-vs-not-trigger-pls

委任しないでください: 60%遅くなります

(初期.trigger化は、jQueryが委任されたイベントをキャッシュする場合に備えて行われます。これは、テストに影響を与えると思います)。

1つのアイテムのみをトリガーする

次に、委任を使用しない方が、特定の1つのアイテムでイベントをトリガーする方が速いと考えました。これも間違っていました:

http://jsperf.com/on-delegate-vs-not-trigger-one

委任しないでください: 80%遅くなります

これは、最後の兄弟ではなく、以前の兄弟の1つであっても同様です。

http://jsperf.com/on-delegate-vs-not-trigger-one-eq2

ディープネスティング

最後に、委任によって行われる作業の多くはDOMツリーの解析である必要があると考えました。つまり、深くネストされたDOMで委任を使用し、非常に古い祖先にバインドしてトリガーすると、深くネストされたアイテム自体にバインドしてトリガーするよりも時間がかかります。

これは最終的に正しいことが判明しました:

http://jsperf.com/on-delegate-vs-not-deep-nesting

委任: 90%遅い

結論

ここで記念碑的な結論を出すことはできませんが、使用するDOMが大量にある場合、特にそれが深くネストされている場合は、直接バインドするのではなく、委任を使用してバインドすることを検討してください。

どちらかといえば、これらの例は、イベントをトリガーする子孫に委任要素をできるだけ近づけておく必要があることを私に教えてくれました(とにかく強化されています)。

于 2013-01-31T05:09:54.053 に答える
3

それは最適化の問題です。説明させてください:

$('#items2 .item a').on('click', function(e) {
  console.log("### Items2 click");
});

上記のコードでは、すべてのアンカーに独自のイベントハンドラーがあります。1つのハンドラーだけが同じアクションを実行できるため、メモリの浪費です。

$('#items').on('click', '.item a', function(e) {
  console.log("### Items click"); 
});

また、2番目のコードでは、#itemsバインド後にアンカーを追加する場合、新しいイベントハンドラーを追加する必要はありません。親要素、、は#itemsすでにそれらをカバーしています。

于 2013-01-31T04:45:54.720 に答える