阻止事件冒泡:element.addEventListener与onclick属性的区别

6

我正在使用stopPropagation,从MDC文档中调整代码。

这里有一个问题:如果我像他们所做的那样使用element.addEventListener("click", fname),一切都很好。
但是,当我尝试使用元素的onclick属性(<div onclick="fname();">)附加函数时,传播不会停止。
如果我使用<div onclick="function(ev) {fname();}">,则根本不会调用fname()(我还尝试了使用相同结果的fname(ev)传递)。

有什么想法吗?如果您需要查看代码,请告诉我。

2个回答

10

实际上,您的事件按以下方式执行:

事件触发、捕获阶段、冒泡阶段、事件应用默认操作。

因此,为了停止传播,您可以执行以下操作:

element1.addEventListener('click',fname,true)  // Capturing phase
element1.addEventListener('click',fname,false) // Bubbling phase

fname(event){
  event.stopPropagation();
//event.preventDefault(); is also available here (in both phases I believe)
}

请注意,事件传播只能在冒泡阶段被停止,在此期间仅使用事件处理程序才允许您中断事件。
据我所知,传统方法是...
<div onclick="return fname();">

不允许此功能。


8
当您执行以下操作时:
<div onclick="fname();">

您没有将fname分配为事件处理程序,而是从您的事件处理程序(即为您创建的匿名函数)中调用fname。因此,您的第一个参数是您传递给fname的任何内容,在您引用的代码中,您没有向其中传递任何内容。

您需要:

<div onclick="fname(event);">

但即使这样也不会很可靠,因为它假设自动生成的匿名函数使用名称event接受event参数,或者你正在使用IE或类似IE的浏览器并查看IE的全局window.event属性。

更可靠的方法是这样的:

<div onclick="return fname();">

如果您希望在事件中做任何有趣的事情(或者即使不想这样做),我强烈建议始终使用DOM2方法(addEventListener,在IE9之前的IE上是attachEvent,但参数略有不同)来连接处理程序。

如果fname希望停止传播并阻止浏览器的默认操作,则应返回false


离题:这整个领域是我推荐使用像jQueryPrototypeYUIClosure其他几个库来平滑处理浏览器差异,以便您可以专注于自己的工作。


1
我实际上不赞成使用常用框架,并建议不要这样做。虽然它们有优点,但跨浏览器框架实现可以相当容易地创建。我建议至少先编写自己的自定义框架,这样您就可以完全理解引擎盖下发生的所有事情。这将帮助您避免未来遇到类似问题的困扰!把事情忘在脑后、隐藏起来(放入框架中)是不好的实践!更容易并不意味着更快或更好! - GAgnew
好的,谢谢提醒!我现在会继续使用addEventListener。不过,我通常会在这种情况下使用jQuery。这只是一个快速测试页面,所以我还没有链接到jQ。 - Nathan
1
@Greg:“……可以很容易地创建跨浏览器框架实现……”这么多年来,许多人都这样想过。:-)只需查看任何主要库的源代码,如果您像我一样,您将欣赏利用其他人已经完成的所有调试工作的能力。比如处理Safari在某些情况下会错误地报告select框中选择的项目,或者如何小心地插入script元素以避免遇到奇怪的base元素错误。等等。(续) - T.J. Crowder
@Greg: (继续) 完全同意你必须知道引擎下面发生了什么,但我仍然不会独自飞行,而且在我的同事中我以“哦,这不可能那么复杂,让我们自己做吧...”的倾向而闻名。;-) - T.J. Crowder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接