DOM 事件的理解
一 DOM 事件的级别
- DOM 0:element.onclick=function(){}
- DOM 2:element.addEventListener('click',function(){},false)
- DOM 3:element.addEventListener('keyup',function(){},false)(定义方式和 2 一样,但是类型增加了很多,比如说鼠标事件,键盘事件)
- 注意:DOM 1 只是对之前各大厂商的 DOM api 做了整理而实施的标准,所以我们认为 DOM 1 的事件处理和 DOM 0 的事件处理是一样的
二 事件模型

-
在W3C中规定,当事件发生后,最先通知 window,然后是 document,开始往下依次进入直到最底层被触发的那个元素(也就是目标元素,通常是 event.target 的值),这个过程就是捕获,事件会从目标元素开始,冒泡,由下至上逐层传递至 window,这个过程就是冒泡
-
之前我们提到的 addEventListener 还有第三个参数,可以为 true 和 false,默认是 false,当第三个参数为 true 时,绑定的是捕获阶段的事件,在捕获阶段,事件是由上到下依次触发的,反之当第三个参数为 false 时,绑定的是冒泡阶段的事件,在冒泡阶段,事件是由下到上触发的
三 事件流
- 浏览器在为当前页面和用户做交互的时候,比如说点击了鼠标左键,这个左键是怎么传到页面上的,页面是怎么响应的,这个就是事件流
- 一个完整的事件流分为三个部分
四 event 对象常用的属性
event.preventDefault()
:阻止默认事件(a 标签设置点击事件,用这个可以阻止默认跳转事件)
event.stopPropagation()
:阻止冒泡事件
event.stopImmediatePropagation()
:注册两个 click 事件,可以在第一个事件中阻止第二个事件触发
event.currentTarget
:当前绑定事件的元素
event.target
:当前被点击的元素
五 自定义事件
事件本质上是一种通信方式,是一种消息,只有在多对象多模块时,才有可能需要使用事件进行通信,在多模块化开发中,可以使用自定义事件进行模块间通信
目前实现自定义事件的两种方式是 js 原生的 Event()
构造函数和 CustomEvent()
构造函数来创建,两者的区别是 CustomEvent
可以在第二个参数中传递一个 detail 对象传递一些信息
<h1 id="elem">Hello from the script!</h1>
<script>
// 在 document 上捕获...
document.addEventListener('hello', function (event) {
// (1)
alert('Hello from ' + event.target.tagName) // Hello from H1
})
// ...在 elem 上 dispatch!
let event = new Event('hello', { bubbles: true }) // (2)
elem.dispatchEvent(event)
// 在 document 上的处理程序将被激活,并显示消息。
</script>
<h1 id="elem">Hello for John!</h1>
<script>
// 事件附带给处理程序的其他详细信息
elem.addEventListener('hello', function (event) {
alert(event.detail.name)
})
elem.dispatchEvent(
new CustomEvent('hello', {
detail: { name: 'John' },
})
)
</script>
六 事件委托
- 事件委托就是利用事件冒泡,只需制定一个事件处理程序,就可以管理某一类型的所有事件,通过事件委托,可以做到通过在祖先元素添加一个事件处理程序,就可以控制其子孙元素的某些行为
- 比如说为 ul 下面所有的 li 添加 click 事件对应的行为处理
- 还有一个常见的利用事件委托的例子,就是点开浮层/关闭浮层,我们常常利用事件委托来监听元素外空间区域的点击来关闭浮层
- 不是所有事件都是可以委托的,适合用事件委托的事件有:
click
/ mousedown
/ keydown
/ keyup
/ keypress