事件模型是JS里十分重要的一个部分,这两天查询了一些相关资料,用自己的文字记录一下。本文不讨论IE。

事件模型

DOM事件模型

最简单且兼容所有浏览器的事件模型,有两种方式。默认发生在冒泡阶段。

HTML中直接绑定(不推荐)

JS指定属性值

var button = document.getElementById("button")button.onclick = function() { //...}

DOM 2级模型

属于W3C标准模型,先事件捕获,到达目标后再进行冒泡。兼容现代浏览器。

//DOM 2级事件第三个参数是一个布尔值(默认为false),true表示捕获阶段调用事件处理程序,false表示冒泡阶段调用事件处理程序。var button = document.getElementById("button")button.addEventListener('click', function() { //...}, false)

DOM 0级和DOM 2级事件模型比较

移除监听函数

button.onclick = nullbutton.removeEventListener('click', click, false)//注意,addEventListener()添加的匿名函数无法移除

同时绑定多个监听器

button.onclick = function() { console.log(1)}button.onclick = function() { console.log(2)}button.addEventListener('click', function() { console.log(3)}, false)button.addEventListener('click', function() { console.log(4)}, false)// 2 3 4

可见DOM0 级后绑定的函数会把前边的替换掉,而DOM 2级可以同时绑定多个监听器,因此推荐使用addEventListener方法监听事件。

监听函数内部的this都指向触发事件的那个元素节点。

var button = document.getElementById("button")button.onclick = function() { console.log(this.id)}button.addEventListener('click', function() { console.log(this.id)}, false)//输出结果均为"button"

事件流

首先我们要先了解一下事件流。事件流描述的是在页面中接受的事件顺序。看下面的例子

//JS var container = document.getElementById("container") var button = document.getElementById("button") button.onclick = function() {alert('button!')} container.onclick = function() {alert('container!')}

当你点击button按钮时,会发生在button按钮上的单击事件,但同时,你也单击了container元素甚至是单击了整个页面。JS事件模型是一种观察者模式(又叫发布订阅者模式),当对应的事件被触发时,监听该事件的所有监听函数都会被调用。因此,如果你单击的多个元素都绑定了相同事件,他们执行的事件顺序是怎么样的呢?

事件流有两种:

事件冒泡:事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接受,然后逐渐向上传播到较不具体的那个节点。

事件捕获:与事件冒泡相反。事件最开始由不太具体的节点最早接受事件, 而最具体的节点最后接受事件。

document -> ->

-> ->