掌握事件冒泡

Posted

技术标签:

【中文标题】掌握事件冒泡【英文标题】:Mastering event bubbling 【发布时间】:2012-09-09 15:40:06 【问题描述】:

假设我们有一个这样的 html 结构

<div id="container">
    <div id="nested">
        <span id="someElement"></span>
    </div>
</div>

...我们的目标是在#container only 上有一个事件监听器!所以,我们绑定一个监听器(jQuery 代码)

$("#container").on('click', function(event) 
    alert("container was clicked");
);

这当然可行,但我对这种方法的问题是,由于事件通常会冒泡,如果我们实际单击 #nested#someElement,该侦听器也会触发。我目前在点击#container 时处理点击的解决方案是将thisevent.target 进行比较

$("#container").on('click', function(event) 
    if(this === event.target) 
        alert("container was clicked");
    
);

我的问题:这被认为是“最佳实践”吗?有没有更好的方法使用 jQuery 来实现“开箱即用”的相同结果?

实际示例:http://jsfiddle.net/FKX7p/

【问题讨论】:

IMO,这是最佳做法。 @jSang:实际上内部元素在点击时没有任何监听器。这被认为是最佳做法吗?绑定每个元素只是为了停止传播? 我也没有看到任何更好的方法,事实上,我正准备将其作为答案发布,直到我看到您已经拥有该代码。 【参考方案1】:

防止事件冒泡的另一种方法是使用 event.stopPropagation();

$("#container").on('click', function(event) 
    alert("container was clicked");
)
.children().on('click', function(event) 
    event.stopPropagation();
);

我认为使用这种方法的好处是,如果你想将另一个事件附加到嵌套的 div 中,你可以使用

$("#nested").on('click', function(event) 
    event.stopPropagation();
    // some action
);

$("#container").on('click', function(event) 
    alert("container was clicked");
);​

【讨论】:

【参考方案2】:

我不确定哪个工作更快,但下一个代码会更好是有道理的:

$("#container").click(function (e) 
    if (e.target.id && e.target.id !== "container") return false;
);

【讨论】:

现在我只检查标识符,使用复杂的选择器除了比较对象之外我看不到其他方法【参考方案3】:

替代解决方案:

$("#container").click(function()
    alert("container was clicked");
).children().click(function(e) 
    return false;
);

但是您的解决方案更好。 jsfiddle.net/FKX7p/2/(返回 false)或 jsfiddle.net/FKX7p/3/(使用 stopPropagation)

我更喜欢在您的示例中使用 return(代码变得更容易阅读):

if(this !== event.target) return;

【讨论】:

另外在需要时使用event.CurrentTarget !== event.Target而不是this,因为使用jQuery.proxy时this的上下文可能发生变化:api.jquery.com/jQuery.proxy 另一种解决方案更糟糕,因为它添加了很多事件处理程序。 @naugtur 我同意你的观点,但在on 功能之前,这个解决方案很受欢迎。 如果流行 != 好然后是的 ;) 比较 target 和 currentTarget 更好。 (注意我没有给你-1;主要是因为我曾经做过这样的事情) @naugtur 是的,你是对的。我想指出没有人给我-1 :)

以上是关于掌握事件冒泡的主要内容,如果未能解决你的问题,请参考以下文章

JS-阻止冒泡事件与事件委托

jQuery事件冒泡及解决办法

事件冒泡以及取消事件冒泡方法

事件冒泡和事件捕获

HTML如何阻止事件冒泡?求源码分析

事件冒泡 & 阻止事件冒泡