当我使用 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');
});
- 然后“验证”处理程序被调用两次。
- 当我深入研究 JQuery 源代码时,我发现 JQuery 会找到事件目标的父节点并检查选择器是否匹配。
- 如果匹配选择器,处理程序队列将再推一个handleobj。在示例中,在事件目标和侦听器元素 div#contianer 之间,有两个分层 div。
- 结果,处理程序队列有两个事件处理程序,它们是相同的事件处理程序函数实例。
我的问题是:如何正确使用选择器来防止事件处理程序被多次调用?谢谢。
我认为要回答这个问题,我们应该仔细阅读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 });
}
}
}
}