js四种事件处理程序

随着W3C不断推进DOM事件模型和IE浏览器事件模型的历史变化,为了方便理解,程序员们中逐渐形成 四种事件处理程序 的概念划分。


提示:本文章内容最后修改时间为2017年07月,部分内容可能已经过时

在 JavaScript 中,通常分为四种事件处理程序:

  1. HTML内联事件处理程序
  2. DOM0事件处理程序
  3. DOM2事件处理程序
  4. IE事件处理程序

HTML内联 DOM0级 DOM2级 IE【后于2022年报废】
代码形式 onclick="fun()" btn.onclick = fun(){} addEventListener() attachEvent()
触发阶段 冒泡阶段 冒泡阶段 冒泡/捕获阶段皆可 冒泡阶段

HTML内联事件处理程序

在HTML的内联属性中添加事件处理。

<button onclick="alert('Hello world!')">按钮</button>

如上,可直接在onclick = ""里添加执行语句;也可如下,调用一个函数:

<button onclick="showMessage()">按钮</button>
<script> function showMessage(){ alert("Hello world!"); } </script>
  • 优势: 代码直观、方便。
  • 劣势: 放任其中前1种写法会导致html和javascript重度耦合,代码不易读。
    • 而在现今,比如Vue.js,框架与使用者通过规范化代码能够削弱“代码耦合”这种缺点,越来越多的主流JavaScript框架都是推崇这种内联属性的写法。

DOM0级事件处理程序

var element = document.getElementById("myBtn"); 
element.onclick = function(){
//操作
};

在事件的冒泡阶段触发回调。

  • 优势: 具有跨浏览器的优势。
  • 劣势:只能绑定1个回调函数
    • 因为直接赋值给对应 DOM object 属性,如果你在后面代码中再次为 element 绑定一个回调函数,会覆盖掉之前回调函数的内容。通俗来说就是很难实现多个绑定。
    • 虽然也可以用一些小技巧实现多个绑定,但还是推荐下面的DOM2级事件处理程序实现多个绑定

1级DOM-----(为什么没有1级DOM)

DOM级别1于1998年10月1日成为W3C推荐标准。1级DOM标准中并没有定义事件相关的内容,所以没有所谓的1级DOM事件模型。在2级DOM中除了定义了一些DOM相关的操作之外还定义了一个事件模型 ,这个标准下的事件模型就是我们所说的2级DOM事件模型

DOM2级事件处理程序

var btn = document.getElementById('btn');
btn.addEventListener('click', function(){ 
  alert('你点击了这里');
}, false);

addEventListener是标准的事件处理程序,亦称为绑定事件监听,提供三个参数可供传递。(IE9+也支持addEventListener)

第三个参数是一个布尔值,true表示在捕获阶段被处理,false表示在冒泡阶段被处理,考虑到浏览器的兼容问题,一般使用false

优势: 可以为一个元素添加多个事件处理程序。

IE事件处理程序

【对于许多年前】IE 浏览器就是特立独行,它对于事件的操作与标准有一些差异。不过 IE 浏览器现在也开始慢慢努力改造,让浏览器变得更加标准。

【对于2022年后】IE正式宣布报废。只有极少数装着旧Windows系统的机器在用。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){ 
  alert("Clicked");
});

(IE事件处理程序:IE5到IE10支持,IE11就不再支持了。但是最好应用于IE5到IE8,因为IE9之后又略有变化)

实际上与addEventListener的使用十分相似。

区别在于,第二个参数传入的是onclick而并非click,且IE只支持在冒泡阶段进行程序处理,所以没有第三个参数布尔值的选择。

此外,如果为同一个元素添加了两个事件处理程序,addEventListener会以添加的顺序依次执行事件处理,而attachEvent则相反。

如果要封装兼容attachEvent和addEventListener:因为attachEvent没有第三个参数,也就是说attachEvent只支持监听冒泡,所以为了与IE表现一致,在使用addEventListener的时候第三参数设置为 false。

总结

  • 一般情况下为了最大限度发挥事件处理程序的作用,使用标准事件处理程序,即addEventListener,并且把第三个参数设为false
  • 如果专门为了兼容IE,则使用attachEvent;
  • 如果是在编写一个小demo,为了简单快捷,可以使用DOM0级处理程序或者考虑HTML内联处理程序。

所谓的跨浏览器的事件处理程序代码,就是基于以上这些api来实现的。

附录

DOM0移除事件绑定

如果想要移除element的“点击事件绑定”,将其置为null即可:

element.onclick = null

DOM2移除事件监听

需要注意的是,绑定事件时的回调函数一般不能是匿名函数, 必须是一个声明的函数,因为解除事件绑定时需要传递这个回调函数的引用,才可以断开绑定。例如:

var fun = function() {
    // function logic
};

element.addEventListener('click', fun, false);
element.removeEventListener('click', fun, false);

IE移除事件监听

detachEvent(),用法与DOM2级的removeEventListener类似

函数作用域

最直观的查看办法就是在函数回调里面加debugger,触发回调后,就能在控制台看到其作用域。

讨论事件处理程序的作用域的意义不大:一般意义上的作用域主要服务于“变量的访问”,而正好 事件处理程序 的“根层级函数”基本上都是靠dom、不需要依靠作用域来实现“变量的访问”。

文章目录
  1. HTML内联事件处理程序
  2. DOM0级事件处理程序
  3. DOM2级事件处理程序
  4. IE事件处理程序
  5. 总结
  6. 附录
    1. DOM0移除事件绑定
    2. DOM2移除事件监听
    3. IE移除事件监听
    4. 函数作用域