addEventListeneronclick有什么区别?

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

上面的代码一起驻留在单独的.js文件中,并且它们都可以正常工作。

最佳答案

两种方法都是正确的,但是它们本身都不是“最佳”的,并且开发人员选择使用这两种方法可能是有原因的。

事件侦听器(addEventListener和IE的attachEvent)

较早版本的Internet Explorer与几乎所有其他浏览器相比,实现javascript的方式有所不同。在版本小于9的情况下,您可以使用attachEvent [doc]方法,如下所示:

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

在大多数其他浏览器(包括IE 9和更高版本)中,您使用addEventListener [doc],如下所示:
element.addEventListener('click', function() { /* do stuff here*/ }, false);

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

上面的示例表示使用匿名函数[doc]。您还可以使用函数引用[doc]或闭包[doc]添加事件侦听器:
var myFunctionReference = function() { /* do stuff here*/ }

element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);
addEventListener的另一个重要功能是final参数,该参数控制侦听器对冒泡事件的 react [doc]。我在示例中传递了错误,这可能是95%用例的标准。 attachEvent或使用内联事件时没有等效的参数。

内联事件(HTML onclick =“”属性和element.onclick)

在所有支持javascript的浏览器中,您都可以内嵌事件监听器,这意味着HTML代码中的内容。您可能已经看到了:
<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>

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

您提到的另一种方法:
element.onclick = function () { /*do stuff here */ };

除了可以更好地控制范围(因为您正在编写脚本而不是HTML),并且可以使用匿名函数,函数引用和/或闭包之外,...等效于内联javascript。

内联事件的主要缺点是,与上述事件侦听器不同,您可能只分配了一个内联事件。内联事件存储为元素[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框架最佳实践涉及在模板中编写此类代码,那么您就不会觉得自己在使用内联事件-并不是。

最好?

问题是浏览器的兼容性和必要性。您是否需要将多个事件附加到一个元素?你将来会吗?很有可能,你会的。 attachEvent和addEventListener是必需的。如果不是这样,则内联事件似乎可以解决问题,但是为将来做准备更好,尽管看起来似乎不太可能,但至少可以预见。您有机会必须转向基于JS的事件侦听器,因此您最好从那里开始。不要使用内联事件。

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 specification, element Event Handler Attributes
  • element.addEventListener on MDN
  • element.attachEvent on MSDN
  • Jquery.on
  • quirksmode blog "Introduction to Events"
  • CDN-hosted javascript libraries at Google
  • 关于javascript - addEventListener与onclick,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6902033/

    10-12 06:04