addEventListener vs onclick

2022-08-29 22:14:23

和 有什么区别?addEventListeneronclick

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

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


答案 1

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

Event Listeners (addEventListener and IE's attachEvent)

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

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

在大多数其他浏览器(包括IE 9及更高版本)中,您使用[doc],如下所示:addEventListener

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);

的另一个重要特性是最终参数,它控制侦听器对冒泡事件的反应[doc]。我在示例中一直在传递错误,这可能是95%用例的标准。没有等效的参数,或者 当使用内联事件时。addEventListenerattachEvent

内联事件(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]的特性/属性,这意味着它可以被覆盖。

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

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

...当您单击该元素时,您只会看到“Did stuff #2” - 您用第二个值覆盖了第一个分配的属性,并且还覆盖了原始的内联HTML属性。在这里查看:http://jsfiddle.net/jpgah/onclickonclick

从广义上讲,不要使用内联事件。它可能有特定的用例,但如果你不能100%确定你有这个用例,那么你就不会也不应该使用内联事件。

现代Javascript(Angular等)

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

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

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

哪个是最好的?

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

jQuery和其他javascript框架将DOM Level 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/

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

文档和相关阅读


答案 2

如果您有其他几个函数,您可以看到的差异:

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 不起作用。这是因为不会覆盖现有的事件处理程序,而会覆盖任何现有的事件处理程序。addEventListeneronclickonclick = fn

当然,另一个显着的区别是它将始终有效,而在版本9之前的Internet Explorer中不起作用。您可以在 IE <9 中使用类似方法(语法略有不同)。onclickaddEventListenerattachEvent