19

私はこのようなマークアップをいくつか持っています(クラスは説明のためだけです):

<ol id="root" class="sortable">
  <li>
    <header class="show-after-collapse">Top-Line Info</header>
    <section class="hide-after-collapse">
      <ol class="sortable-connected">
        <li>
          <header class="show-after-collapse">Top-Line Info</header>
          <section class="hide-after-collapse">
            <div>Content A</div>
          </section>
        </li>
      </ol>
    </section>
  </li>
  <li>
    <header/>
    <section class="hide-after-collapse">
      <ol class="sortable-connected">
        <li>
          <header/>
          <section class="hide-after-collapse">
            <div>Content B</div>
          </section>
        </li>
      </ol>
    </section>
  </li>
</ol>

つまり、ネストされた並べ替え可能なリストです。ただし、ソート可能なプラグインで十分です。内部のリストは接続されていますが、各 li (以下、「アイテム」) はそのレベルを維持するためです。アイテムには、常に表示されるヘッダーと、展開された状態のときに表示されるセクションがあり、ヘッダーをクリックすると切り替えられます。ユーザーは、どちらのレベルからでも項目を自由に追加および削除できます。トップレベルのアイテムを追加すると、その中に空のネスト リストが含まれます。私の質問は、新しく作成されたアイテムの JS 初期化に関するものです。それらはいくつかの共通機能を共有しますが、

$("#root").on("click", "li > header", function() {
  $(this).parent().toggleClass("collapsed");
});

li.collapsed section {
  display: none;
}

(補足質問: これは HTML5 の詳細/要約タグを使用するのに適切な場所でしょうか?最終的な仕様にそれが組み込まれるかどうかについては、やや不確かなようです。とにかくそれには JS が必要です.しかし、私は大衆に質問を投げかけます.こんにちは、大衆.)

ルート リストが、ページの読み込み時に存在することが保証されている唯一の (関連する) 要素である場合、.on() が効果的に機能するには、すべてのイベントをその要素にバインドし、それぞれの正確なセレクターを綴る必要があります。それを理解します。したがって、たとえば、別々の機能を隣り合わせの 2 つのボタンに関連付けるには、セレクターを毎回完全にスペルアウトする必要があります。

$("#root").on("change", "li > section button.b1", function() {
  b1Function();
}).on("change", "li > section button.b2", function() {
  b2Function();
});

それは正確ですか?その場合、新しいアイテムがページに追加されたときに .on() を忘れてイベントをバインドする方が理にかなっていますか? 応答に違いが生じる場合、アイテムの総数はおそらくせいぜい数十になるでしょう。

4

2 に答える 2

44

$(<root-element>).on(<event>, <selector>)潜在的により多くの単一の子孫要素ではなく、単一の「ルート」要素にバインドするため、イベントをバインドする際の CPU オーバーヘッドが少なくなります(各バインドには時間がかかります...)。

そうは言っても、実際のイベントが発生すると、DOM を「ルート」要素にバブルアップする必要があるため、より多くの CPU オーバーヘッドが発生します。

簡単な話:デリゲートは、イベント ハンドラーをバインドするときに CPU を節約します。bind は、イベントがトリガーされたときに CPU を節約します(たとえば、ユーザーが何かをクリックしたとき)。

したがって、パフォーマンスにとってどのポイントがより重要かを判断するのはあなた次第です。新しい要素を追加するときに使用可能な CPU はありますか? その場合、新しい要素に直接バインドするのが全体的なパフォーマンスに最適ですが、要素の追加が CPU を集中的に使用する操作である場合は、おそらくイベント バインドを委任し、イベント トリガーがすべてのバブリングから余分な CPU オーバーヘッドを作成できるようにすることをお勧めします。

ご了承ください:

$(<root-element>).on(<event>, <selector>, <event-handler>)

以下と同じです:

$(<root-element>).delegate(<selector>, <event>, <event-handler>)

そしてそれ:

$(<selector>).on(<event>, <event-handler>)

以下と同じです:

$(<selector>).bind(<event>, <event-handler>)

.on()は jQuery 1.7 の新機能であり、1.7 以降を使用している場合は.delegate(<selector>, <event>, <event-handler>).on(<event>, <selector>, <event-handler>).

アップデート

各要素に個別にバインドするよりもイベント バインディングを委任する方が高速であることを示すパフォーマンス テストを次に示します: http://jsperf.com/bind-vs-click/29残念ながら、このパフォーマンス テストは削除されました。

アップデート

以下は、バインディングをデリゲートするのではなく、要素に直接バインドした方がイベントのトリガーが高速であることを示すパフォーマンス テストです: http://jsperf.com/jquery-delegate-vs-bind-triggering (これは完全なパフォーマンスではないことに注意してくださいバインディングメソッドはテストに含まれているため、テストしますが、バインディングでより高速に実行されるため、トリガーについて話すときに相対的にさらに高速delegateであることを意味します)bind

于 2012-01-11T22:19:00.060 に答える
14

受け入れられた回答には不正確なテストが含まれているため(ところで:コードをテストし、パフォーマンスを測定し、いくつかの「ルール」にやみくもに従わないでください-これは最適化の方法ではありません!)そして単に間違っているので、固定テストを投稿します: https:// jsperf.com/jquery-delegate-vs-bind-triggering/49

このような単純な例では、委任と直接バインディングの間に違いはないことが証明されています

委任が常に悪い唯一のケースは、マウスの移動やスクロールなどのイベントであり、1 秒あたり x 回トリガーされます。これは、パフォーマンスの違いに気付く場所です。

クリックなどの単一のイベントで 1 ミリ秒の差 (発生しませんが、これは単なる例です) がある場合は、それに気付かないでしょう。1 秒間に 100 回発生するイベントに 1 ミリ秒の差がある場合、CPU の消費に気付くでしょう。

数千の要素を持っているだけで、委任によるパフォーマンスに悪影響を与えることはありません。実際には、委任を使用する必要がある場合です。これは、数千のイベント ハンドラーをアタッチするときに CPU を占有しないようにするためです。

したがって、従うべきルールが本当に必要な場合 (そうしないでください) - マウスの移動、スクロール、および継続的に発生することが予想されるその他のイベントを除くすべてに委任を使用します。

于 2015-12-25T16:26:29.460 に答える