addEventListeneronclick有什么区别?

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

上面的代码一起驻留在一个单独的数据库中.js文件,它们都工作得很好.

推荐答案

这两种方法都是正确的,但它们本身都不是"最好的",这可能是开发人员 Select 使用这两种方法的原因.

Event Listeners (addEventListener and IE's 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或使用内联事件时没有等效参数.

Inline events (HTML onclick="" property and 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'); };

...当您单击该元素时,您将看到"Do Stuff#2"-您用第二个值覆盖了onclick属性的第一个赋值,也覆盖了原始的内联HTMLonclick属性.看看这里:http://jsfiddle.net/jpgah/.

一般说来,是do not use inline events.它可能有特定的用例,但是如果您不是百分之百确定您有这个用例,那么您不会也不应该使用内联事件.

Modern Javascript (Angular and the like)

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

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

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

Which is Best?

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

jQuery和其他javascript框架将DOM level 2事件的不同浏览器实现封装在通用模型中,因此您可以编写跨浏览器兼容的代码,而无需担心IE作为叛逆者的历史.与jQuery相同的代码,都是跨浏览器的,随时可以摇滚:

$(element).on('click', function () { /* do stuff */ });

不过,不要跑出go ,只为这一件事找一个框架.您可以轻松地使用自己的小实用程序来处理较旧的浏览器:

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版本中不起作用.

Documentation and Related Reading

Javascript相关问答推荐

如何在alpinejs中显示dev中x-for的元素

JavaScript文本区域阻止KeyDown/KeyUp事件本身上的Alt GR +键组合

node TS:JWT令牌签名以验证客户端和后台问题之间的身份验证

在Angular中将样式应用于innerHTML

使用复选框在d3.js多折线图中添加或删除线条

Msgraph用户邀请自定义邮箱模板

在观察框架中搜索CSV数据

成功完成Reducers后不更新状态

如何控制Reaction路由加载器中的错误状态?

变量的值在Reaction组件中的Try-Catch语句之外丢失

material UI按钮组样式props 不反射

在浏览器中触发插入事件时检索编码值的能力

如何在箭头函数中引入or子句?

如何将zoom 变换应用到我的d3力有向图?

变量在导入到Vite中的另一个js文件时成为常量.

自定义图表工具提示以仅显示Y值

将嵌套数组的元素乘以其深度,输出一个和

如何在Web项目中同步语音合成和文本 colored颜色 更改

使用静态函数保存 node 前的钩子

将字符串解释为数字;将其重新编码为另一个基数