一尘不染

JavaScript addEventListener与onclick

javascript

addEventListener和之间有什么区别onclick

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

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


阅读 501

收藏
2020-04-22

共1个答案

一尘不染

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

事件监听器(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);

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

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

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

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

另一个重要特点addEventListener是最后的参数,它控制如何监听到做出反应的事件冒泡
[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。

内联事件的主要缺点是,与上述事件侦听器不同,你可能只分配了一个内联事件。内联事件存储为element [doc]的属性/属性,这意味着可以覆盖它。

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

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

…当你单击该元素时,你 只会 看到“第2件东西”-你onclick用第二个值覆盖了属性的第一个分配值,也覆盖了原始的内联HTML
onclick属性。

广义上讲, 不要使用内联事件 。可能有特定的用例,但是如果你不是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!'); }
);

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

2020-04-22