资讯专栏INFORMATION COLUMN

[译] addEventListener 与 onclick,孰优孰劣?

wums / 612人阅读

摘要:上面的例子应用了匿名函数这个特性,还可以使用构造函数或者闭包来添加事件监听器另一个重要特性,则是上面这段代码中最后一行的最后一个参数,用来控制监听器对于冒泡事件的响应。在这里你不能使用闭包或者匿名函数,并且控制域也是有限的。

原文出处:addEventListener vs onclick

之所以会想到这个话题,是因为在回顾自己之前写的为 button 动态绑定事件的函数时,脑海里忽然浮现出了一个问题:addEventListener 方法,与 onclick="" 相比,各有哪些优点和缺点呢?于是用关键字“StackOverflow addEventListener click func false”进行搜索,第二个结果就是上面的文章链接,现将全文摘要如下:

绑定事件有几种方式:

Event Listeners

(addEventListener 以及 IE 的 attachEvent)

IE 8 以及更低版本的 IE 中,需要用 attachEvent 方法:

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

对于 IE 9 和更高版本的 IE,以及其它浏览器,则要用 addEventListener 方法:

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

用上面这种方法(DOM level 2 events),理论上可以为一个元素绑定无数个事件,实际应用中则决定于客户端的电脑内存以及浏览器。

上面的例子应用了匿名函数这个特性,还可以使用构造函数或者闭包来添加事件监听器:

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

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

另一个重要特性,则是上面这段代码中最后一行的最后一个参数,用来控制监听器对于冒泡事件的响应。95%的使用场景中,这个参数都为 falseattachEvent 以及内联事件则都没有可以实现相同功能的这个参数。

Inline Events 内联事件

(HTML 的 onclick="" 属性,以及 element.onclick)

在所有支持 JavaScript 的浏览器中,可以用下面的方式来添加内联的事件监听器。

Click me

虽然很多有经验的开发人员对这种方式嗤之以鼻,但是它的确足够的简单粗暴。在这里你不能使用闭包或者匿名函数,并且控制域也是有限的。

还有另一种方法:

element.onclick = function () { /*do stuff here */ };

这个方法能实现相同的效果,并且有更多的控制域(因为是 JS 脚本,而不是 HTML 代码),当然了,也能使用匿名函数、构造函数、闭包。

内联事件一个明显的不足:由于内联事件是作为元素属性保存起来的,这些属性可以被覆盖,所以如果为同一个事件绑定了多个处理程序,那么最后一个处理程序会覆盖之前的程序(多谢 @谦龙 指出此处的翻译错误)。

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

运行上面的示例,将只会看到“did stuff #2”——第二行代码覆盖了默认的内联 onclick 属性,第三行代码又将第二行代码覆盖了,所以会产生这样的结果。

谁是最佳方案?

要回答这个问题,就要考虑各个浏览器的兼容性,以及实际需求了。即使现在只需要为一个元素绑定一个事件,但是以后很可能还要同时再绑定别的事件,这个时候,就需要用 attachEventaddEventListener 了,否则用内联方法就可以搞定了。

jQuery 以及其它的 JavaScript 框架,已经将各个浏览器的 DOM level 2 events 的实现以通用模型的形式封装起来了,所以通过 jQuery 可以很方便地写出适用于所有浏览器的代码:

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

在解决问题的时候,不要简单地就事论事,比如这篇文章讨论的就是如何添加事件监听器,那就不妨写一个适用于所有浏览器的方法:

function addEvent(element, evnt, funct){
  // if else 结构可用三元运算符 ? : 来精简
  // 这里之所以要这样写,是便于读者理解
  if (element.attachEvent) // IE 8 及更低版本浏览器
   return element.attachEvent("on"+evnt, funct);
  else // IE 8 及以上,或其它浏览器
   return element.addEventListener(evnt, funct, false);
}

// 调用示例
addEvent(
    document.getElementById("myElement"),
    "click",
    function () { alert("hi!"); }
);
相关文献

W3 HTML specification, element Event Handler Attributes

element.addEventListener on MDN

element.attachEvent on MSDN

Jquery.on

quirksmode blog "Introduction to Events"

CDN-hosted javascript libraries at Google

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79556.html

相关文章

  • 个人文章分类整理

    摘要:春节闲来无事,看看自己在上写的文章,想不到已经篇了,各方面的都有,那就分类整理一下吧,也方便自己和别人查看。 春节闲来无事,看看自己在SegmentFault上写的文章,想不到已经20篇了,各方面的都有,那就分类整理一下吧,也方便自己和别人查看。 CSS CSS Background-Size 属性小记 [译]关于垂直居中 Vertical Align 的探讨 [译]CSS 居中(...

    OnlyLing 评论0 收藏0
  • 个人文章分类整理

    摘要:春节闲来无事,看看自己在上写的文章,想不到已经篇了,各方面的都有,那就分类整理一下吧,也方便自己和别人查看。 春节闲来无事,看看自己在SegmentFault上写的文章,想不到已经20篇了,各方面的都有,那就分类整理一下吧,也方便自己和别人查看。 CSS CSS Background-Size 属性小记 [译]关于垂直居中 Vertical Align 的探讨 [译]CSS 居中(...

    v1 评论0 收藏0
  • 个人文章分类整理

    摘要:春节闲来无事,看看自己在上写的文章,想不到已经篇了,各方面的都有,那就分类整理一下吧,也方便自己和别人查看。 春节闲来无事,看看自己在SegmentFault上写的文章,想不到已经20篇了,各方面的都有,那就分类整理一下吧,也方便自己和别人查看。 CSS CSS Background-Size 属性小记 [译]关于垂直居中 Vertical Align 的探讨 [译]CSS 居中(...

    nidaye 评论0 收藏0
  • 个人文章分类整理

    摘要:春节闲来无事,看看自己在上写的文章,想不到已经篇了,各方面的都有,那就分类整理一下吧,也方便自己和别人查看。 春节闲来无事,看看自己在SegmentFault上写的文章,想不到已经20篇了,各方面的都有,那就分类整理一下吧,也方便自己和别人查看。 CSS CSS Background-Size 属性小记 [译]关于垂直居中 Vertical Align 的探讨 [译]CSS 居中(...

    heartFollower 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<