addEventListener和onclick有什么区别?

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

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


当前回答

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

《捉鬼列表和衰人》

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

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

在大多数其他浏览器(包括ie9及以上)中,您使用addEventListener[doc],如下所示:

element.addEventListener('click', function() { /* do stuff here*/ }, false);

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

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

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

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

addEventListener的另一个重要特性是final参数,它控制监听器如何对冒泡事件做出反应。我在示例中传递了false,这可能是95%用例的标准。对于attachEvent,或者在使用内联事件时,没有等效的参数。

内联事件(HTML onclick=""属性和元素。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”——你用第二个值覆盖了onclick属性的第一个赋值,你也覆盖了原始的HTML内嵌onclick属性。点击这里查看:http://jsfiddle.net/jpgah/。

一般来说,不要使用内联事件。它可能有特定的用例,但是如果您不能100%确定您有这个用例,那么您就不应该也不应该使用内联事件。

现代Javascript (Angular之类的)

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

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

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

哪个是最好的?

The question is a matter of browser compatibility and necessity. Do you need to attach more than one event to an element? Will you in the future? Odds are, you will. attachEvent and addEventListener are necessary. If not, an inline event may seem like they'd do the trick, but you're much better served preparing for a future that, though it may seem unlikely, is predictable at least. There is a chance you'll have to move to JS-based event listeners, so you may as well just start there. Don't use inline events.

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规范,元素事件处理程序属性 元素。addEventListener在MDN 元素。attachEvent在MSDN上 Jquery.on quirksmode博客“事件介绍” cdn托管的javascript库在谷歌

其他回答

简介:

addEventListener可以添加多个事件,而onclick则不能这样做。 onclick可以作为HTML属性添加,而addEventListener只能添加在<script>元素中。 addEventListener可以接受第三个参数,该参数可以停止事件传播。

两者都可用于处理事件。然而,addEventListener应该是首选的选择,因为它可以做onclick做的所有事情,甚至更多。不要使用内联onclick作为HTML属性,因为这会混淆javascript和HTML,这是一个坏的做法。它使代码更难维护。

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

《捉鬼列表和衰人》

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

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

在大多数其他浏览器(包括ie9及以上)中,您使用addEventListener[doc],如下所示:

element.addEventListener('click', function() { /* do stuff here*/ }, false);

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

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

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

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

addEventListener的另一个重要特性是final参数,它控制监听器如何对冒泡事件做出反应。我在示例中传递了false,这可能是95%用例的标准。对于attachEvent,或者在使用内联事件时,没有等效的参数。

内联事件(HTML onclick=""属性和元素。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”——你用第二个值覆盖了onclick属性的第一个赋值,你也覆盖了原始的HTML内嵌onclick属性。点击这里查看:http://jsfiddle.net/jpgah/。

一般来说,不要使用内联事件。它可能有特定的用例,但是如果您不能100%确定您有这个用例,那么您就不应该也不应该使用内联事件。

现代Javascript (Angular之类的)

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

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

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

哪个是最好的?

The question is a matter of browser compatibility and necessity. Do you need to attach more than one event to an element? Will you in the future? Odds are, you will. attachEvent and addEventListener are necessary. If not, an inline event may seem like they'd do the trick, but you're much better served preparing for a future that, though it may seem unlikely, is predictable at least. There is a chance you'll have to move to JS-based event listeners, so you may as well just start there. Don't use inline events.

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规范,元素事件处理程序属性 元素。addEventListener在MDN 元素。attachEvent在MSDN上 Jquery.on quirksmode博客“事件介绍” cdn托管的javascript库在谷歌

let element = document.queryselector('id or classname'); 
element.addeventlistiner('click',()=>{
  do work
})

<button onclick="click()">click</click>`
function click(){
  do work
};

如果你有另外两个函数,你可以看到区别:

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之前的ie中不能工作。你可以在IE <9中使用类似的attachEvent(语法略有不同)。

在我的Visual Studio代码中,addEventListener对事件有真实的智能感知

但onclick没有,只有假的