Javascript添加事件跨浏览器功能实现:使用attachEvent/addEventListener vs inline events

Posted

技术标签:

【中文标题】Javascript添加事件跨浏览器功能实现:使用attachEvent/addEventListener vs inline events【英文标题】:Javascript add events cross-browser function implementation: use attachEvent/addEventListener vs inline events 【发布时间】:2011-04-15 08:28:36 【问题描述】:

为了添加事件,我们可以使用这个简单的第一种解决方案

function AddEvent(html_element, event_name, event_function) 
       
   if(html_element.attachEvent) //Internet Explorer
      html_element.attachEvent("on" + event_name, function() event_function.call(html_element);); 
   else if(html_element.addEventListener) //Firefox & company
      html_element.addEventListener(event_name, event_function, false); //don't need the 'call' trick because in FF everything already works in the right way          
 

或此第二个解决方案(添加内联事件):

function AddEvent(html_element, event_name, event_function) 
       
   var old_event = html_element['on' + event_name];
   if(typeof old_event !== 'function')
      html_element['on' + event_name] = function()  event_function.call(html_element); ;
   else
      html_element['on' + event_name] = function()  old_event(); event_function.call(html_element); ;

这些都是跨浏览器,可以这样使用:

AddEvent(document.getElementById('some_div_id'), 'click', function() 
             
   alert(this.tagName); //shows 'DIV'
);  

由于我感觉attachEvent/addEventListener 在事件处理实现中使用得更多,我想知道:

使用第二种解决方案有什么缺点/缺点吗?

我可以看到两个,但我对更多(如果有的话)感兴趣:

    第二种解决方案通过添加内联事件来破坏元素的 innerHTML 使用第二种解决方案,我可以轻松删除与特定事件类型 (html_element['on' + event_name] = null) 关联的所有函数,但我无法使用 detachEvent/removeEventListener 删除完全特定的函数。

任何诸如“使用 jQuery”或任何其他 FW 之类的答案都是毫无意义的!

【问题讨论】:

你忘了event参数 @Bergi:在哪里,什么? 在所有这些event_function.call(…) 表达式中。调用处理程序时没有 event! 谢谢,但我认为将事件传递给event_function 不是强制性的。我同意你的观点,如果事件处理程序想要对事件做一些事情,它需要事件参数。 “这不是强制性的”是什么意思?我以为你想写一个通用的 addeventlistener 函数。您无法知道处理程序不使用事件对象。 【参考方案1】:

使用第二个解决方案,您必须手动调用以前的函数,这使得删除特定的侦听器变得困难(在我看来,这听起来像是您想要而不是清除所有侦听器),而在第一个解决方案中,你只能同时清除它们,除非你想模拟第一个功能。

就个人而言,我总是使用第一种解决方案,因为它的优点是不必担心清除可能的其他事件侦听器。

mozilla wiki 还列出了第一个解决方案适用于任何 DOM 元素的优点,而不仅仅是 HTML 元素,并且它允许对第三个解决方案激活侦听器时的阶段进行更细粒度的控制(捕获与冒泡)论据。

【讨论】:

我认为您在前两段中将第一件事和第二件事倒退了。 +1 我阅读了您建议的链接,但 Mozilla 网站解释的三点并非如此:“1. 它允许为事件添加多个处理程序”是正确的,但我使用了这两个功能在回答中写道,您可以添加多个事件处理程序。 “2.当侦听器被激活时,它可以让您更细粒度地控制阶段(捕获与冒泡)”是的,但添加 stopEvent 函数以防止默认和停止冒泡很容易,而且 attachEvent 没有这样的行为,所以会anyayw 必须创建一个跨浏览器功能。 (续)“3。它适用于任何 DOM 元素,而不仅仅是 HTML 元素。”,很有趣,但我没有看到可能需要向dom 节点,它也不是 HTML 元素。 @Marco Demaio:1. 对。但是您的功能是非本地的,任何其他想要注册事件的人都会清除整个 onload。 2. 真的 3. SVG 标签?【参考方案2】:

我会像这样使用这两个代码

function addEvent(html_element, event_name, event_function) 
    if (html_element.addEventListener)  // Modern
        html_element.addEventListener(event_name, event_function, false);
     else if (html_element.attachEvent)  // Internet Explorer
        html_element.attachEvent("on" + event_name, event_function);
     else  // others
        html_element["on" + event_name] = event_function;
    
;

【讨论】:

以上是关于Javascript添加事件跨浏览器功能实现:使用attachEvent/addEventListener vs inline events的主要内容,如果未能解决你的问题,请参考以下文章

js实现一些跨浏览器的事件方法

js 实现一些跨浏览器的事件方法详解及实例

JavaScript 经典实例收集整理

JavaScript 经典实例收集整理

JavaScript跨浏览器兼容之事件

JavaScript跨浏览器绑定事件函数的优化