什么之间的区别addEventListener
和onclick
?
var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);
上面的代码一起存在于一个单独的 .js 文件中,它们都可以完美地工作。
什么之间的区别addEventListener
和onclick
?
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 ]。我一直在示例中传递 false,这对于大约 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 */ };
... 相当于内联 javascript,除了您可以更好地控制范围(因为您正在编写脚本而不是 HTML)并且可以使用匿名函数、函数引用和/或闭包。
内联事件的显着缺点是与上述事件侦听器不同,您可能只分配了一个内联事件。内联事件存储为元素 [ doc ]的属性/属性,这意味着它可以被覆盖。
使用<a>
上面 HTML 中的示例:
var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };
...当您单击该元素时,您只会看到“Did stuff #2” - 您onclick
用第二个值覆盖了该属性的第一个分配,并且您也覆盖了原始的内联 HTMLonclick
属性。在这里查看: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 版本中使用。
文档和相关阅读
如果您有另外几个功能,您可以看到不同之处:
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 之前的 Internet Explorer 中不起作用。您可以在 IE <9 中使用类似的attachEvent
(语法略有不同)。
在这个答案中,我将描述定义 DOM 事件处理程序的三种方法。
element.addEventListener()
代码示例:
element.addEventListener()
具有多重优势:
element.removeEventListener()
.useCapture
参数,它指示你是想在它的捕获阶段还是冒泡阶段处理事件。请参阅:无法理解 addEventListener 中的 useCapture 属性。.onevent
DOM 元素的属性,许多没有经验的 JavaScript 程序员认为事件名称是例如onclick
或onload
。on
是不是事件名称的一部分。正确的事件名称是click
和load
,这就是将事件名称传递给 的方式.addEventListener()
。element.onevent = function() {}
(例如onclick
, onload
)代码示例:
这是一种在 DOM 0 中注册事件处理程序的方法。现在不鼓励这样做,因为它:
onevent
属性恢复到其初始状态(即null
)。window.onload
,例如: window.onload = "test";
,它不会抛出任何错误。您的代码不起作用,而且很难找出原因。.addEventListener()
但是,会抛出错误(至少在 Firefox 中):TypeError: Argument 2 of EventTarget.addEventListener is not an object。onevent
HTML 属性)代码示例:
与 类似element.onevent
,现在不鼓励使用。除了存在的问题外element.onevent
,它还:
Content-Security-Policy
HTTP 标头来阻止内联脚本,并只允许来自受信任域的外部脚本。请参阅内容安全策略如何工作?虽然onclick
适用于所有浏览器,addEventListener
但不适用于旧版本的 Internet Explorer,而是使用attachEvent
。
缺点onclick
是只能有一个事件处理程序,而另外两个将触发所有注册的回调。
addEventListener
可以添加多个事件,而onclick
不能这样做。onclick
可以作为HTML
属性添加,而 anaddEventListener
只能添加在<script>
元素中。addEventListener
可以采用可以停止事件传播的第三个参数。两者都可以用来处理事件。但是,addEventListener
应该是首选,因为它可以做任何事情onclick
,甚至更多。不要将内联onclick
用作 HTML 属性,因为这会混淆 javascript 和 HTML,这是一种不好的做法。它使代码的可维护性降低。