addEventListener和onclick有什么区别?

var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);

上面的代码一起驻留在一个单独的.js文件中,它们都可以完美地工作。


当前回答

一个元素对每种事件类型只能有一个事件处理程序,但可以有多个事件监听器。


那么,它的实际情况如何呢?

只有最后分配的事件处理程序才会运行:

const button = document.querySelector(".btn")
button.onclick = () => {
  console.log("Hello World");
};
button.onclick = () => {
  console.log("How are you?");
};
button.click() // "How are you?" 

所有事件监听器将被触发:

const button = document.querySelector(".btn")
button.addEventListener("click", event => {
  console.log("Hello World");
})
button.addEventListener("click", event => {
  console.log("How are you?");
})
button.click() 
// "Hello World"
// "How are you?"

IE注:attachEvent不再支持。从IE 11开始,使用addEventListener: docs。

其他回答

虽然onclick可以在所有浏览器中工作,但addEventListener不能在旧版本的Internet Explorer中工作,后者使用attachEvent代替。

onclick的缺点是只能有一个事件处理程序,而其他两个将触发所有注册的回调。

在我的Visual Studio代码中,addEventListener对事件有真实的智能感知

但onclick没有,只有假的

你也应该考虑eventdelegate ! 因此,我更喜欢addEventListener,最重要的是小心谨慎地使用它!

事实:

eventlistener是沉重的....(客户端内存分配) 事件在与DOM的关系中传播IN,然后再次传播OUT 树。也被称为涓滴式和冒泡式,读一读 以防你不知道。

想象一个简单的例子: 一个简单的按钮内部div内部主体… 如果你点击按钮,一个事件将无论如何 滴入到BUTTON,然后再OUT,像这样:

window-document-div-button-div-document-window

在浏览器后台(比如JS引擎的软件外围),浏览器只能对点击做出反应,如果它检查了每一次点击的目标位置。

为了确保每个可能的事件监听器都被触发,它必须从文档级别一直发送“点击事件信号”到元素中。然后再回来。 这个行为可以通过附加eventlistener来使用,例如:

document.getElementById("exampleID").addEventListener("click",(event) => {doThis}, true/false);

请注意,作为addEventListener方法最后一个参数的true/false控制了何时识别事件的行为——何时流入或何时流出。

TRUE表示事件在传入时被识别 FALSE表示事件在冒泡输出的过程中被识别

实现以下2个有用的概念,使用上述方法处理问题也会更加直观:

You can also use event.stopPropagation() within the function (example ref. "doThis") to prevents further propagation of the current event in the capturing and bubbling phases. It does not, however, prevent any default behaviors from occurring; for instance, clicks on links are still processed. If you want to stop those behaviors, you could use event.preventDefault() within the function (example ref. "doThis"). With that you could for example tell the Browser that if the event does not get explicitly handled, its default action should not be taken as it normally would be.

还需要再次注意这里的参考:addEventListener方法的最后一个参数(true/false)也控制了“. stoppropagation()”的最终效果在哪个阶段生效(涓滴为true或冒头为false)。 所以…如果你将一个带有TRUE标志的EventListener应用到一个元素,并将其与.stopPropagation()方法结合起来,事件甚至不会通过元素的潜在内部子元素

总结一下: 如果你在HTML中使用onClick变体…对我来说有两个缺点:

与addEventListener,你可以附加多个onClick事件到相同的,分别是一个单一的元素,但这是不可能使用onClick(至少这是我坚信到目前为止,如果我错了,请纠正我)。 以下方面也确实值得注意……特别是代码维护部分(到目前为止还没有详细说明):

In regards to event delegation, it really boils down to this. If some other JavaScript code needs to respond to a click event, using addEventListener ensures you both can respond to it. If you both try using onclick, then one stomps on the other. You both can't respond if you want an onclick on the same element. Furthermore, you want to keep your behavior as separate as you can from the HTML in case you need to change it later. It would suck to have 50 HTML files to update instead of one JavaScript file. (credit to Greg Burghardt, addEventListener vs onclick with regards to event delegation )

这也被称为“Unobtrusive JavaScript”…读一读吧!

也可以通过对侦听器进行原型化(如果我们有对它的引用,而且它不是匿名函数)来扩展侦听器,或者使onclick调用成为对函数库的调用(函数调用其他函数)。

如:

elm.onclick = myFunctionList;
function myFunctionList(){
    myFunc1();
    myFunc2();
}

这意味着我们永远不需要改变onclick调用,只需要改变myFunctionList()函数来做任何我们想做的事情,但这让我们无法控制冒泡/捕获阶段,所以应该避免在新浏览器中使用。

如果你有另外两个函数,你可以看到区别:

var h = document.getElementById('a');
h.onclick = doThing_1;
h.onclick = doThing_2;

h.addEventListener('click', doThing_3);
h.addEventListener('click', doThing_4);

函数2、3和4可以工作,但函数1不行。这是因为addEventListener不会覆盖现有的事件处理程序,而onclick会覆盖任何现有的onclick = fn事件处理程序。

当然,另一个重要的区别是onclick总是可以工作,而addEventListener在版本9之前的ie中不能工作。你可以在IE <9中使用类似的attachEvent(语法略有不同)。