addEventListener和onclick有什么区别?

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

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


当前回答

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

但onclick没有,只有假的

其他回答

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

但onclick没有,只有假的

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

《捉鬼列表和衰人》

早期版本的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
};

如果你不太担心浏览器的支持,有一种方法可以在事件调用的函数中重新绑定'this'引用。它通常指向在函数执行时生成事件的元素,这并不总是您想要的。棘手的部分是同时能够删除相同的事件侦听器,如本例所示:http://jsfiddle.net/roenbaeck/vBYu3/

/*
    Testing that the function returned from bind is rereferenceable, 
    such that it can be added and removed as an event listener.
*/
function MyImportantCalloutToYou(message, otherMessage) {
    // the following is necessary as calling bind again does 
    // not return the same function, so instead we replace the 
    // original function with the one bound to this instance
    this.swap = this.swap.bind(this); 
    this.element = document.createElement('div');
    this.element.addEventListener('click', this.swap, false);
    document.body.appendChild(this.element);
}
MyImportantCalloutToYou.prototype = {
    element: null,
    swap: function() {
        // now this function can be properly removed 
        this.element.removeEventListener('click', this.swap, false);           
    }
}

上面的代码在Chrome上运行得很好,并且可能有一些关于“绑定”与其他浏览器兼容的问题。

我想Chris Baker在一个很好的答案中总结了它,但我想添加到addEventListener()中,你也可以使用options参数,它可以让你更好地控制你的事件。例如,如果你只想运行你的事件一次,那么你可以在添加事件时使用{once: true}作为一个选项参数,只调用它一次。

    function greet() {
    console.log("Hello");
    }   
    document.querySelector("button").addEventListener('click', greet, { once: true })

上面的函数只打印“Hello”一次。 此外,如果你想清理你的事件,那么还有removeEventListener()选项。虽然使用addEventListener()有优点,但如果您的目标受众使用Internet Explorer,则此方法可能并不适用于所有情况,您仍然应该小心。你也可以在MDN上读到addEventListener,他们对如何使用它们给出了很好的解释。