【问题标题】:Do event attributes always fire before event listeners?事件属性总是在事件侦听器之前触发吗?
【发布时间】:2017-01-05 18:09:18
【问题描述】:

我为表单提交设置了两个侦听器。一个是在onsubmit 属性中指定的,另一个是使用event listener 指定的。

根据我的测试,属性中指定的总是首先触发。总是这样吗?事件属性会总是先触发吗?或者有没有这种情况不会发生的情况?

function attribute(e) {
  console.log('Attribute');
  e.preventDefault();
}

function listener(e) {
  console.log('Listener');
  e.preventDefault();
}

document.querySelector('form').addEventListener('submit', listener);
<form onsubmit="attribute(event)">
  <button type="submit">Submit</button>
</form>

我知道using event attributes should be "avoided",这更像是一个理解问题。

【问题讨论】:

  • 我不会依赖它。而是使用addEventListener 添加所有侦听器,它们(相同类型的事件)保证按定义的顺序触发。
  • 是的,我同意你的看法。甚至出现这个问题的原因是因为我有一个第 3 方表单验证插件,只要 JS 可用于供应商捆绑包中的页面,它就会始终附加。我无法改变它的位置。由于应用程序架构,我的 JS 代码是在供应商捆绑包之后加载的。因此,验证器 JS 总是在我的代码之前触发 :( 。虽然我不会走添加事件属性的路线,但我仍然很好奇这是否总是如此。
  • onclick.addEventListener("click") 之前被调用。无法在规范中找到预期结果的详细信息,但似乎优先于元素处的style 属性
  • @KevBot 见Default action "&lt;A HREF="somewhere.html" onClick="doSomething()"&gt; 在点击链接的情况下,必须先执行事件处理程序。毕竟,当默认动作发生时——new页面已加载——旧页面(包括事件处理程序)已从浏览器内存中删除。因此,如果要执行 onclick 事件处理程序,则必须在默认操作之前完成。”
  • The specs 说:“同步事件(“同步事件”)被视为在先进先出模型中的虚拟队列中”。在附加事件之前,元素必须存在。这意味着,在 JS 可以创建其事件之前,属性事件已被推送到队列中。如果第三方脚本使用事件委托,事情会变得更加复杂。您可以尝试删除第三方侦听器,并在附加自己的侦听器后重新附加它(当然,如果您可以获得对第三方处理函数的引用)。

标签: javascript html attributes event-handling dom-events


【解决方案1】:

我会假设在您的情况下它们首先触发,因为属性标记首先得到处理,但不能保证所有浏览器都会如此。此外,即使在仅调用 addEventListener() 的情况下,也不能保证在 DOM 3 之前的顺序。但是,在 DOM 3 上,事件侦听器将按照它们注册的顺序执行。在此处查看接受的答案:How do multiple addEventListener work in JavaScript?

为了保证事件监听器会在 onclick 之前被调用,你可以实现类似下面的东西。此示例根据您的 sn-p 更改调用顺序,以便您可以在属性定义事件之前放置任意代码。

<html>
<head>
<script>
function attribute(e) {
  console.log('Attribute');
  e.preventDefault();
}

function listener(e) {
  console.log('Listener');
  e.preventDefault();
}
window.onload = function() { 
     var form = document.querySelector('form');
     var f = form.onsubmit; 
     form.onsubmit = null;
     form.addEventListener('submit', function(e) {listener(e); f(e);});
}
</script>
</head>

<body>
<form onsubmit="attribute(event)">
  <button type="submit">Submit</button>
</form>
</body>
<html>

【讨论】:

  • 问题是:“事件属性会总是先触发吗?”仅仅用一个浏览器测试一个案例很难回答这个问题。
  • 这个例子适用于任何浏览器。我只是没有测试它。它总是会在属性之一之前更改顺序并触发侦听器函数。 KevBot 解释了他为什么想知道这一点,这是因为他使用了一个第三方库,该库在属性上添加事件,并且它们在他添加的事件之前触发。虽然属性在特定浏览器中可能优先于侦听器或不优先于侦听器,但我发布的代码将始终有效,并且会在属性中声明的事件之前触发所需的事件。我会尽量让答案更清楚。谢谢。
  • 如何确保您的代码在任何浏览器中都以相同的方式运行?即使标准明确说明事件触发的顺序是这样的,您也不能确定所有实现都确实这样做。浏览器会做一些奇怪的事情,尤其是 IE。另外,我了解到,OP 考虑添加内联事件处理程序,因为第三方插件使用addEventListener 添加自己的事件,并且 OP 希望在此插件之前触发自己的侦听器-in-listener。
  • OP 声明“我的 JS 代码是在供应商捆绑后加载的”,因此可以更改顺序。请检查这个 sn-p,我明确地改变了顺序:
  • 对不起,这个 sn-p: var form = document.querySelector('form'); var f = form.onsubmit; form.onsubmit = null; form.addEventListener('submit', function(e) {listener(e); f(e);});
猜你喜欢
  • 2020-09-06
  • 1970-01-01
  • 2015-12-18
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-14
  • 1970-01-01
相关资源
最近更新 更多