一、事件流
js中事件流分为两个阶段:捕获阶段,冒泡阶段;
简单描述就是当页面上某个元素触发了一个事件,比如点击事件,这个事件不仅会触发当前元素节点上绑定的事件回调函数,还会触发该元素的所有祖先节点上绑定的同类型事件的回调函数,那么这个触发的过程,就可以理解为事件流。这个触发的顺序是从根节点开始,向下查找(捕获阶段),一直到触发事件的元素,然后再从这个元素开始反向查找(冒泡阶段),一直到根节点,沿途所有节点,只要绑定了相应的事件处理函数,会依次执行。
<html>
<body>
<div></div>
<script>
// addEventListener()的第三个参数,false表示绑定在冒泡阶段,true表示绑定在捕获阶段
document.documentElement.addEventListener('click', function() {
console.log('html1')
}, true)
document.body.addEventListener('click', function() {
console.log('body1')
}, true)
document.querySelector('div').addEventListener('click', function() {
console.log('div1')
}, true)
document.documentElement.addEventListener('click', function() {
console.log('html2')
})
document.body.addEventListener('click', function() {
console.log('body2')
})
document.querySelector('div').addEventListener('click', function() {
console.log('div2')
})
</script>
</body>
</html>
上面的代码,如果点击了div元素,则会依次触发
html1
body1
div1
div2
body2
html2
二、事件代理
事件代理是利用了事件流的特点,将事件绑定在某一个祖先节点上,当子节点触发事件时,统一在祖先节点的事件处理函数中处理逻辑。
这种形式主要是优化大量子节点绑定相同事件处理函数的性能开销,以及子节点需要频繁操作(增删)时重复绑定与解绑的问题。