on() を使用してイベントをリッスンしているときに、イベント ハンドラーが複数回呼び出されていることがわかりました。以下のようにコードします。
html:
<div id="container">
<div>
<div><input type="text"/></div>
</div>
</div>
JS:
var $div = $('#container'), $input = $('input');
$div.on('validate', 'div', function() {
console.log('div');
});
$input.blur(function() {
$(this).trigger('validate');
});
- 次に、「検証」ハンドラーが 2 回呼び出されます。
- JQuery ソース コードを掘り下げると、JQuery がイベント ターゲットの親ノードを検出し、セレクターが一致するかどうかを確認することがわかります。
- セレクターと一致した場合、ハンドラー キューは、handleobj をもう 1 つプッシュされます。この例では、イベント ターゲットとリスナー要素 div#contianer の間に、2 つの階層 div があります。
- その結果、ハンドラー キューには、同じイベント ハンドラー関数インスタンスである 2 つのイベント ハンドラーがあります。
私の質問は次のとおりです:イベントハンドラーが複数回呼び出されるのを防ぐためにセレクターを正しく使用する方法は? ありがとう。
この質問に答えるには、関連する JQuery のソース コードを注意深く読む必要があると思います。
// Determine handlers that should run if there are delegated events
// Avoid non-left-click bubbling in Firefox (#3861)
if ( delegateCount && !(event.button && event.type === "click") ) {
// Pregenerate a single jQuery object for reuse with .is()
jqcur = jQuery(this);
jqcur.context = this.ownerDocument || this;
for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
// Don't process events on disabled elements (#6911, #8165)
if ( cur.disabled !== true ) {
selMatch = {};
matches = [];
jqcur[0] = cur;
for ( i = 0; i < delegateCount; i++ ) {
handleObj = handlers[ i ];
sel = handleObj.selector;
if ( selMatch[ sel ] === undefined ) {
selMatch[ sel ] = (
handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
);
}
if ( selMatch[ sel ] ) {
matches.push( handleObj );
}
}
if ( matches.length ) {
handlerQueue.push({ elem: cur, matches: matches });
}
}
}
}