事件触发有三个阶段
① window 往事件触发处传播,遇到注册的捕获事件会触发
② 传播到事件触发处时触发注册的事件
③ 从事件触发处往 window 传播,遇到注册的冒泡事件会触发
注册事件,最后一个参数若为 boolean
false - 注册程序在冒泡阶段触发
true - 注册程序在捕获阶段触发
下面这段代码可以看到其中的原理
<!DOCTYPE html> <html lang="en"> <head> <title>事件机制</title> <meta charset="utf-8"> <style> body, button { font-size: 50px; } </style> </head> <body> <button id="button">事件测试</button> <script> var button = document.getElementById('button') // 注册事件,最后一个参数若为 boolean // false - 注册程序在冒泡阶段触发 // true - 注册程序在捕获阶段触发 // 触发位置上注册事件,无论是冒泡还是捕获 // 均是按照注册的顺序执行 button.addEventListener('click', e => { console.log('按钮 - 冒泡2') }, false) button.addEventListener('click', e => { console.log('按钮 - 捕获2') }, true) button.addEventListener('click', e => { console.log('按钮 - 捕获1') }, true) button.addEventListener('click', e => { console.log('按钮 - 冒泡1') }, false) // 非触发位置,则先执行捕获,再执行冒泡 document.body.addEventListener('click', e => { console.log('body - 冒泡2') }, false) document.body.addEventListener('click', e => { console.log('body - 冒泡1') }, false) document.body.addEventListener('click', e => { console.log('body - 捕获2') }, true) document.body.addEventListener('click', e => { console.log('body - 捕获1') }, true) </script> </body> </html>
上述代码在控制台的输出为(点击按钮之后):
body - 捕获2 body - 捕获1 按钮 - 冒泡2 按钮 - 捕获2 按钮 - 捕获1 按钮 - 冒泡1 body - 冒泡2 body - 冒泡1
最后一个参数也可以为 object 对象,key 值含义如下所示:
{ capture: false, // 布尔值,false - 冒泡, true - 捕获 once: false, // 布尔值,值为 true 表示该回调只会调用一次,调用后会移除监听 passive: false // 布尔值,表示永远不会调用 preventDefault }