32

.on()jQueryのメソッドをネイティブJSに実装する方法を知っている人はいますか?このaddEventListenerメソッドは、フィルタリングの方法として子/セレクター要素を取りません。また、そこで何が起こっているのかを完全に理解するための適切なバブリング/キャプチャーの知識がないと思います。私はevent.jsでソースを調べましたが、最終的にaddEventListenerは通常どおりに使用されるように見えますが、ソースを完全に理解したかどうかはわかりません。

ネイティブメソッドがバブリングとキャプチャを利用するメカニズムを提供しない場合、jQuery.on()関数には実際に何らかの利点がありますか、それともそのように見えるだけですか?私はその印象を受けました

.on('parent', '.child', fn(){});

すべての子に個別にイベントを添付するよりも効率的ですが、ソースの私の解釈から、jQueryがパフォーマンスの向上につながる方法でこれを管理しているのか、それとも読みやすさのためだけなのかを判断するのは困難です。

個々の子にイベントを添付するのではなく、子要素のバブリング/キャプチャフェーズを利用するイベントを親に実装するための標準的な方法はありますか?

4

2 に答える 2

30

イベント委任をネイティブに実行するには:

parent.addEventListener('click', function(e) {
    if(e.target.classList.contains('myclass')) {
        // this code will be executed only when elements with class 
        // 'myclass' are clicked on
    }
});

参照している効率は、追加するイベント ハンドラーの数に関係しています。100 行のテーブルを想像してください。単一のイベント ハンドラーをテーブル要素にアタッチしてから各行に「委任」する方が、100 個のイベント ハンドラーを各行に 1 つずつアタッチするよりもはるかに効率的です。

イベント委譲が機能する理由は、クリック イベントが子と親の両方で実際に発生するためです (親内の領域をクリックしているため)。上記のコード スニペットは、親のクリック イベントで発生しますが、条件がイベントターゲットに対して true を返した場合にのみ実行され、直接アタッチされたイベント ハンドラーをシミュレートします。

バブリング/キャプチャーは関連する問題ですが、複数のイベント ハンドラーが起動する順序が問題になる場合にのみ、心配する必要があります。バブリングとキャプチャの理解に興味がある場合は、イベントの順序についてさらに読むことをお勧めします。

イベント委任の最も一般的な利点は、イベント ハンドラーがアタッチされた後に DOM に追加される新しい要素を処理できることです。クリック ハンドラーを含む 100 行のテーブルの上記の例を見てみましょう。直接のイベント ハンドラー アタッチメント (100 個のイベント ハンドラー) を使用する場合、追加される新しい行には、イベント ハンドラーを手動で追加する必要があります。委任されたイベントを使用する場合、新しい行は自動的にイベント ハンドラーを「持つ」ことになります。これは、将来のすべてのイベントを取得する親に技術的に追加されているためです。詳細については、Felix Kling が提案したWhat is DOM Event Delegationを参照してください。

于 2014-01-30T20:40:42.740 に答える
0

受け入れられた答えへの追加:多くの場合、実際のイベントターゲットはリスナーをバインドする要素内にネストされるため、親をクエリする方がよいでしょう(Element.closest()には要素自体が含まれます)。また、これは単一のクラスだけではなく、複雑な CSS セレクターでも機能します。

<button><span>button with</span><span>multiple click targets</span></button>

function addListener(el, type, callbackFn, selector) {
    el.addEventListener(type, e => {
        const target = e.target.closest(selector);
        if (target) callbackFn.call(target, e);
    }, true);
}
addListener(document, "click", e => console.log("clickediclick"), "button");
于 2021-12-16T14:06:13.910 に答える