Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 内联onclick与addeventlistener的顺序是什么?为什么?_Javascript_Html - Fatal编程技术网

Javascript 内联onclick与addeventlistener的顺序是什么?为什么?

Javascript 内联onclick与addeventlistener的顺序是什么?为什么?,javascript,html,Javascript,Html,考虑一下这个按钮: <button id="the_button" onclick="RunOnClick();">Click</button> 在addEventListener中注册的处理程序似乎总是在内联onclick=”“之后运行 我是否可以始终依赖于单个内联onclick处理程序先触发,然后再触发addEventListener处理程序 这是侥幸吗?或者它实际上是这样设计的,并且是ECMAScript规范的一部分 这感觉像是回到了问题的基本性质,但我不知道答案

考虑一下这个按钮:

<button id="the_button" onclick="RunOnClick();">Click</button>
addEventListener
中注册的处理程序似乎总是在内联
onclick=”“
之后运行

我是否可以始终依赖于单个内联
onclick
处理程序先触发,然后再触发
addEventListener
处理程序

这是侥幸吗?或者它实际上是这样设计的,并且是ECMAScript规范的一部分


这感觉像是回到了问题的基本性质,但我不知道答案。

这不是侥幸,你可以指望它会表现得那样……在你使用的浏览器中。但是,它在其他浏览器中的行为可能会有所不同!这取决于浏览器实现事件规范的方式,规范不需要任何特定的顺序

根据下面的评论,澄清一下:我想指出的是,它可能会在您今天使用的浏览器中以同样的方式运行。直到你得到一个更新,或者一些你意想不到的变化。不管怎样,依赖规范中没有的东西是一个非常糟糕的主意


如果您需要有保证的顺序,最好的解决方案是将事件处理程序链接起来,只触发一个与相关事件相关的事件。

虽然这种行为在您使用的浏览器中可能会重复,但不能保证另一个浏览器(甚至同一浏览器的不同版本)会以相同的方式运行

这是因为每个渲染引擎都为触发事件处理程序设置了自己的优先级,通常是按照事件处理程序的附加顺序设置的


如果需要确保特定的执行顺序,可以设置一个在单个处理程序上触发的事件队列。

答案是,是的,这实际上包含在规范中,但不包括ECMAScript规范本身,ECMAScript规范本身只严格处理独立于实现的ECMAScript

首先,DOM事件的顺序。我请你参考这个相关的问题

正如这句话所说,以前它并没有具体说明,但到目前为止,它确实明确说明了它们应该按照注册的顺序执行

但是像您的示例中定义的内联事件处理程序呢

为此,我们可以求助于如下的例子:

事件处理程序内容属性是特定事件处理程序的内容属性。内容属性的名称与事件处理程序的名称相同

[……]

当实现EventTarget接口的元素或对象的事件处理程序
H
首次设置为非空值时,用户代理必须将事件侦听器附加到与
T
关联的事件侦听器列表中,并将type设置为与
H
对应的事件处理程序事件类型,将回调设置为下面定义的事件处理程序处理算法

将此注释和后续注释稍加解包,这里需要带走的关键内容是:

  • 添加“事件处理程序内容属性”(例如,
    onclick
    属性)的行为将导致将事件侦听器添加到DOM规范前面提到的列表中
  • 在幕后实际发生的事情是,严格来说,此事件侦听器不是在
    onclick
    属性中指定的代码,而是用于评估属性和执行适当回调的内部事件处理程序处理算法
  • 重要的是,当属性更改或设置为null时,事件侦听器及其在列表中的位置不会更改。只更改事件处理程序处理算法的结果(因为您更改了输入)
这可能有点混乱。自己阅读和消化规范中的注释可能会有所帮助,但我也将尝试涵盖以下关键含义

首先,是的,您看到的行为由规范有效地定义,作为规范告诉我们的逻辑结果。当解析文档并遇到内联事件处理程序属性时,此内部算法将立即添加到事件侦听器列表中。根据规范,这将意味着第一个事件监听器将是与事件处理程序属性对应的监听器。因为这必须在调用
addEventListener
之前设置,因为无法对当时不存在的元素调用
addEventListener
。在这些情况下,它将始终首先执行

当我们在初始解析之后开始处理内联属性时,就会发生有趣的事情。下面是HTML5规范本身的一个例子,它出现在我上面引用的位之后:

例8

此示例演示调用事件侦听器的顺序。如果用户单击本例中的按钮,页面将显示四个警报,分别显示文本“一”、“二”、“三”和“四”

开始演示
var button=document.getElementById('test');
addEventListener('click',函数(){alert('ONE')},false);
button.setAttribute('onclick',“警报('notcalled')”);//事件处理程序侦听器在此处注册
addEventListener('click',函数(){alert('THREE')},false);
button.onclick=function(){alert('TWO');};
addEventListener('click',函数(){alert('FOUR')},false);
正如我们可以看到的,onclick属性的初始值被覆盖,但是新的onclick处理程序仍然在第一个和第二个侦听器集之间执行,并使用
addEventListener
。这样做的原因是内联事件处理程序将始终有效地位于侦听器列表中,与它第一次添加到元素时的位置相同。这是因为技术上,如前所述
var btn = document.getElementById('the_button');

btn.addEventListener("click", function(){
    // Do Something
});
 <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>