当我使用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中的相关源代码:
// 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 });
}
}
}
}
答案 0 :(得分:0)
$ input.blur(function(){$(this).trigger('validate');});'只有输入触发器 验证事件。因此,我认为这并不意味着“为DOM上的每个元素工作onblur
这是错误的,因为触发器冒出DOM树,并为父元素触发相同的事件。
从jQuery 1.3开始,.trigger()ed事件冒泡了DOM树;事件处理程序可以通过从处理程序返回false或对传递给事件的事件对象调用.stopPropagation()方法来停止冒泡
因此div#container
内有两个div,
$input.blur(function() {$(this).trigger('validate');});
也会触发这两个div。
以下示例显示哪个元素为currentTarget
,
$div.on('validate', 'div', function(e) {
console.log(e.currentTarget);
});
如果你想停止冒泡,只需从该事件中返回false。
$div.on('validate', 'div', function(e) {
console.log(e.currentTarget);
return false;
});
答案 1 :(得分:0)
这意味着:在$ div上绑定'validate'事件,但也为每个div后代包含它。
$div.on('validate', 'div', function() {
console.log('div');
});
请参阅jQuery on
,参数selector
:
用于过滤所选元素后代的选择器字符串 触发事件。如果选择器为null或省略,则为事件 当它到达所选元素时总是被触发。
使用此:
$div.on('validate', function() {
console.log('div');
});
......你只会处理一件事。
答案 2 :(得分:0)
如果您有充分的理由将事件处理程序绑定到 div 而不是 input ,则可以将事件处理程序更改为如下所示:
$div.on('validate', '*', function(event) {
var isRelevant = false;
$(this).children().each(function(){
if (this === event.target){
isRelevant = true;
}
});
if (isRelevant){
console.log('div');
}
});
此代码段会检查事件发出的 event.target (doc)是否是事件传播到的元素的直接子元素之一。 对于内部div, isRelevant 只会是 true 。
您也可以在我的例子中找到它:http://jsfiddle.net/BwseN/