- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
考虑这个按钮:
<button id="the_button" onclick="RunOnClick();">Click</button>
此按钮有一个内联的 onclick
事件处理程序。 RunOnClick
函数的内容对于这个问题无关紧要。
如果我还像这样附加另一个点击事件监听器:
var btn = document.getElementById('the_button');
btn.addEventListener("click", function(){
// Do Something
});
使用 addEventListener
注册的处理程序似乎总是在内联 onclick=""
之后运行。
我能否始终依靠单个内联 onclick
处理程序先触发,然后再触发 addEventListener
处理程序?
这是侥幸吗?或者它实际上是这样设计的并且是 ECMAScript 规范之一的一部分?
这感觉像是一个回到基础的问题,但我不知道答案。
最佳答案
答案是,是的,这实际上包含在规范中,而不是 ECMAScript 规范本身,它只严格处理与实现无关的 ECMAScript。
首先,DOM事件的排序。我建议你引用这个相关的 SO 问题。
Are event handlers in JavaScript called in order?
正如这里所述,之前它是未指定的,但从 DOM level 3 spec 开始它确实明确指出它们应该按照它们注册的顺序执行。
但是像您的示例中那样定义的内联事件处理程序呢?
为此我们可以求助于 HTML 5 spec其中说:
An event handler content attribute is a content attribute for a specific event handler. The name of the content attribute is the same as the name of the event handler.
[...]
When an event handler
H
of an element or objectT
implementing the EventTarget interface is first set to a non-null value, the user agent must append an event listener to the list of event listeners associated withT
with type set to the event handler event type corresponding toH
and callback set to the event handler processing algorithm defined below.
解开这个和随后的注释,这里要带走的关键是:
onclick
属性)的行为将导致事件监听器添加到 DOM 规范前面提到的列表中。onclick
属性中指定的代码,而是一个内部事件处理程序处理算法,用于评估该属性并执行适当的回调。 这可能有点令人困惑。自己阅读和消化规范中的注释可能会有所帮助,但我也会尝试涵盖下面的关键含义。
首先,是的,您看到的行为实际上是由规范定义为规范告诉我们的逻辑结果。当文档被解析并遇到内联事件处理程序属性时,此内部算法会立即添加到事件监听器列表中。根据规范,这意味着第一个事件监听器将是与您的事件处理程序属性对应的事件监听器。因为这必须在任何调用 addEventListener
之前设置,因为不可能在当时不存在的元素上调用 addEventListener
。在这些情况下,它将始终先执行。
有趣的事情发生在我们开始处理初始解析后的内联属性时。这是 HTML5 规范本身的一个示例,它出现在我上面引用的位之后:
EXAMPLE 8
This example demonstrates the order in which event listeners are invoked. If the button in this example is clicked by the user, the page will show four alerts, with the text "ONE", "TWO", "THREE", and "FOUR" respectively.
<button id='test'>Start Demo</button>
<script>
var button = document.getElementById('test');
button.addEventListener('click', function () { alert('ONE') }, false);
button.setAttribute('onclick', "alert('NOT CALLED')"); // event handler listener is registered here
button.addEventListener('click', function () { alert('THREE') }, false);
button.onclick = function () { alert('TWO'); };
button.addEventListener('click', function () { alert('FOUR') }, false);
</script>
正如我们所见,onclick 属性的初始值被覆盖,但是新的 onclick 处理程序仍然在使用 addEventListener
设置的第一个和第二个监听器之间执行。这样做的原因是,内联事件处理程序将有效地始终位于监听器列表中,与它首次添加到元素时的位置相同。这是因为从技术上讲,如前所述,实际的事件监听器不是我们在属性内容中指定的回调,而是将属性内容作为输入的内部算法。
我创建了一个 JSFiddle测试情况是否如此,我可以确认这是我在 Firefox 和 Chrome 中看到的行为。
所以总结一下,在实践方面:
setAttribute
添加的事件处理程序属性,它们将遵循它们添加的顺序,分别对应于对 addEventListener
的较早和较晚的调用。希望一切都解决了!
关于javascript - 内联 onclick 与 addeventlistener 的顺序是什么?为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49805942/
我想在按下按钮时打开一个表单,然后在完成表单后创建另一个按钮以将数据存储在对象中。 我这样做了,但在第二个 addEventListener 中它给了我这个错误: cannot read proper
这是我实际代码的简化版本。 有三个复选框和按钮(每个编号为 0、1、2)和一个提交按钮。简而言之,如果您选中复选框编号 1 和 2,单击提交,按钮 1 和 2 将被着色。现在您可以单击任何彩色按钮,它
问题代码 var el = document.getElementById("searchcharm_'"+touch_id+"'"); el.addEventListener('click',
window.document.addEventListener = function(event) {...} window.addEventListener = function(event) {
这段代码块有什么区别: var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", uploadProgress,
在使用 PhoneGap 时,它有一些使用 document.addEventListener 的默认 JavaScript 代码,但我有自己的代码使用 window.addEventListener
当我运行这段代码时,为什么 .body 事件先触发? document.addEventListener('click', function() { console.log('The docume
我将带有循环的 addEventListener 添加到一些 anchor 元素 products 中,如下所示: for(var j=0;j
所以我的代码可以按我想要的方式工作,但是大多数(IE 除外)调试器都会向我抛出此错误: 未捕获类型错误:无法读取未定义的属性“addEventListener” 这是代码: //Get all ele
我真的不知道为什么这不起作用。在我的 HTML 中,如果我将脚本放在 head 部分,我会在控制台中收到以下错误: Uncaught TypeError: Cannot read property '
在 React 中,当你有一个带有 onClick 属性的元素时,很容易使用 Enzyme 的 .simulate("click") 方法来点击它。然而,在我的代码库中有一个示例,其中一个元素被 Re
问候,由于某种原因,当我单击按钮时,我的 -addEventListener 没有执行。任何人都可以帮忙这是我的代码: function elNegro() { alert("Thank Yo
我正在将我的一些代码从 onClick 更改为 addEventListener,因为我已经阅读了各种好处,并且出于关注点分离的目的。然而,我遇到的问题之一是,虽然使用 onClick,我能够调用一个
我正在尝试向我在循环中生成的某些元素添加事件监听器。我必须使用 div.lastChild - 虽然在这个例子中它非常愚蠢。但这只是演示: var func = function() {
我在将事件监听器添加到 JS 时遇到问题...如果我将按钮与 onclick 属性连接,它会起作用,但如果我在 HTML 中删除它并尝试添加 eventListener('click', myFunc
我不知道为什么,但是当我点击“按钮”时什么也没有发生... 控制台中没有消息,没有错误。如何解决? JS var bird = (function(){ let button = doc
我正在绘制一个方框网格,希望能够单击每个方框并使用 SocketIO 将带有其 ID 的通知发送到服务器 let boxes = document.querySelecto
我想是新手问题。 以下代码是我在文档就绪时调用的函数的一部分。它旨在在鼠标移动时永久返回当前鼠标位置的值。 正在发生的奇怪事情:在文档就绪时移动鼠标不会将任何内容记录到控制台。我知道 mouse_mo
我是 Flash 的新手,我似乎无法完成这个简单的操作。 (我正在使用 ActionScript 3.0) 我在我的编辑器中创建了一个输入文本框。实例名称是“测试”。在我的 Action 编辑器中,我
我有一个像 那些标签包含一些内容,我想打开/关闭它们,但仅使用纯 javascript。我已经尝试过使用 document.querySelectorAll
我是一名优秀的程序员,十分优秀!