addEventListener 与 onclick

新手上路,请多包涵

addEventListeneronclick 有什么区别?

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

上面的代码放在一个单独的 .js 文件中,它们都可以完美运行。

原文由 William Sham 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 737
2 个回答

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

事件监听器(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 的另一个重要特性是 final 参数,它控制监听器如何对冒泡事件做出反应[ doc ]。在示例中,我一直在传递 false,这对于大约 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 */ };

… 相当于内联 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 框架最佳实践涉及在模板中编写此类代码,请不要觉得您在使用内联事件——您不是。

哪个是最好的?

问题是浏览器兼容性和必要性的问题。您是否需要将多个事件附加到一个元素?将来你会吗?很有可能,你会的。 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 的部分在 IE 版本小于 9 中将不起作用。

文档和相关阅读

原文由 Chris Baker 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果你有另外几个功能,你可以看到不同之处:

 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 中不起作用。您可以使用类似的 attachEvent 在 IE 中(语法 略有 不同)。

原文由 lonesomeday 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题