addEventListener和onclick有什么区别?

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

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


当前回答

你也应该考虑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基本上是一个addEventListener,当元素被单击时,它专门执行一个函数。当你有一个做简单操作的按钮时,它很有用,比如计算器按钮。addEventlistener可以用于很多事情,比如在加载DOM或所有内容时执行一个操作,类似于window。Onload,但有更多的控制。

注意,实际上可以使用内联使用多个事件,或者至少可以使用onclick,用分号分隔每个函数,例如....

我不会写一个内联函数,因为你可能会有潜在的问题,这将是混乱的imo。只需使用它来调用脚本文件中已经完成的函数。

你用哪一个取决于你想要什么。addEventListener用于复杂操作,onclick用于简单操作。我见过一些项目没有为元素附加一个特定的事件监听器,而是实现了一个更全局的事件监听器,它将确定是否点击了按钮,并根据所按的按钮执行某些任务。在我看来,这可能会导致潜在的问题,尽管很小,可能,资源浪费,如果事件监听器必须处理每一个点击

addEventListener允许您设置多个处理程序,但在IE8或更低版本中不支持。

IE确实有attachEvent,但它并不完全相同。

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

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

这两种方法都是正确的,但没有一种方法本身是“最好的”,开发人员选择使用这两种方法可能是有原因的。

《捉鬼列表和衰人》

早期版本的Internet Explorer对JavaScript的实现与其他浏览器几乎不同。对于小于9的版本,您使用attachEvent[doc]方法,如下所示:

element.attachEvent('onclick', function() { /* do stuff here*/ });

在大多数其他浏览器(包括ie9及以上)中,您使用addEventListener[doc],如下所示:

element.addEventListener('click', function() { /* do stuff here*/ }, false);

使用这种方法(DOM Level 2事件),理论上可以将无限数量的事件附加到任何单个元素。唯一的实际限制是客户端内存和其他性能问题,这对于每个浏览器都是不同的。

上面的例子表示使用匿名函数[doc]。你也可以使用函数引用[doc]或闭包[doc]来添加事件监听器:

var myFunctionReference = function() { /* do stuff here*/ }

element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);

addEventListener的另一个重要特性是final参数,它控制监听器如何对冒泡事件做出反应。我在示例中传递了false,这可能是95%用例的标准。对于attachEvent,或者在使用内联事件时,没有等效的参数。

内联事件(HTML onclick=""属性和元素。onclick)

在所有支持javascript的浏览器中,您都可以将事件监听器内联,也就是在HTML代码中。你可能看过这个:

<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>

大多数有经验的开发人员都避免使用这种方法,但它确实可以完成工作;它简单直接。这里您不能使用闭包或匿名函数(尽管处理程序本身是某种匿名函数),而且您对作用域的控制是有限的。

你提到的另一种方法:

element.onclick = function () { /*do stuff here */ };

... 它相当于内联javascript,只不过你可以更好地控制作用域(因为你写的是脚本而不是HTML),并且可以使用匿名函数、函数引用和/或闭包。

内联事件的显著缺点是,与上面描述的事件侦听器不同,您可能只分配了一个内联事件。内联事件存储为元素[doc]的属性/属性,这意味着它可以被覆盖。

使用上面HTML中的例子<a>:

var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };

... 当你点击元素时,你只会看到“Did stuff #2”——你用第二个值覆盖了onclick属性的第一个赋值,你也覆盖了原始的HTML内嵌onclick属性。点击这里查看:http://jsfiddle.net/jpgah/。

一般来说,不要使用内联事件。它可能有特定的用例,但是如果您不能100%确定您有这个用例,那么您就不应该也不应该使用内联事件。

现代Javascript (Angular之类的)

自从这个答案最初发布以来,像Angular这样的javascript框架已经变得更加流行。你会在Angular模板中看到这样的代码:

<button (click)="doSomething()">Do Something</button>

这看起来像一个内联事件,但它不是。这种类型的模板将转换为更复杂的代码,在幕后使用事件侦听器。我在这里所写的关于事件的所有内容仍然适用,但你至少从本质上被移除了一层。您应该了解具体细节,但如果您的现代JS框架最佳实践涉及在模板中编写这类代码,不要觉得您在使用内联事件——您不是。

哪个是最好的?

The question is a matter of browser compatibility and necessity. Do you need to attach more than one event to an element? Will you in the future? Odds are, you will. attachEvent and addEventListener are necessary. If not, an inline event may seem like they'd do the trick, but you're much better served preparing for a future that, though it may seem unlikely, is predictable at least. There is a chance you'll have to move to JS-based event listeners, so you may as well just start there. Don't use inline events.

jQuery和其他javascript框架将DOM级别2事件的不同浏览器实现封装在通用模型中,这样您就可以编写跨浏览器兼容的代码,而不必担心IE的反叛历史。相同的代码与jQuery,所有跨浏览器和准备摇滚:

$(element).on('click', function () { /* do stuff */ });

但是,不要仅仅为了这一件事而去找一个框架。你可以很容易地使用自己的小工具来处理旧的浏览器:

function addEvent(element, evnt, funct){
  if (element.attachEvent)
   return element.attachEvent('on'+evnt, funct);
  else
   return element.addEventListener(evnt, funct, false);
}

// example
addEvent(
    document.getElementById('myElement'),
    'click',
    function () { alert('hi!'); }
);

试试吧:http://jsfiddle.net/bmArj/

考虑到所有这些因素,除非您正在查看的脚本以其他方式考虑了浏览器差异(在您的问题中没有显示的代码中),否则使用addEventListener的部分将无法在小于9的IE版本中工作。

文档及相关阅读

W3 HTML规范,元素事件处理程序属性 元素。addEventListener在MDN 元素。attachEvent在MSDN上 Jquery.on quirksmode博客“事件介绍” cdn托管的javascript库在谷歌

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

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(语法略有不同)。