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 2 级事件),您可以将理论上不受限制的事件数量附加到任何单个元素。唯一实际的限制是客户端内存和其他性能问题,这对于每个浏览器都是不同的。
上面的示例表示使用匿名函数 [ 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 ] 的属性 / 属性,这意味着它可以被覆盖。
使用上面 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 版本中将不起作用。
文档和相关阅读
如果您还有其他几个功能,则可以看到的区别:
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()
代码示例:
const element = document.querySelector('a');
element.addEventListener('click', event => event.preventDefault(), true);
<a href="//google.com">Try clicking this link.</a>
element.addEventListener()
具有多个优点:
element.removeEventListener()
删除它们。useCapture
参数,该参数指示您是要在捕获阶段还是冒泡阶段中处理事件。请参阅: 无法理解 addEventListener 中的 useCapture 属性。.onevent
属性,因此许多没有经验的 JavaScript 程序员都认为事件名称为onclick
或onload
。 on
不是事件名称的一部分。 click
并load
正确的事件名称,这就是将事件名称传递给.addEventListener()
。element.onevent = function() {}
(例如onclick
, onload
)代码示例:
const element = document.querySelector('a');
element.onclick = event => event.preventDefault();
<a href="//google.com">Try clicking this link.</a>
这是在 DOM 0 中注册事件处理程序的方法。现在不建议这样做,因为它:
onevent
属性恢复为初始状态(即null
)。window.onload
,例如: window.onload = "test";
,它不会引发任何错误。您的代码将无法正常工作,而且很难找出原因。 .addEventListener()
会引发错误(至少在 Firefox 中): TypeError:EventTarget.addEventListener 的参数 2 不是 object 。onevent
HTML 属性)代码示例:
<a href="//google.com" onclick="event.preventDefault();">Try clicking this link.</a>
与element.onevent
相似,现在不建议使用。 element.onevent
存在的问题之外,它还具有:
Content-Security-Policy
HTTP 标头以阻止内联脚本,并仅允许来自受信任域的外部脚本。请参阅内容安全策略如何工作?