DOM事件机制和事件委托
一、简介
事件流是一个事件沿着特定数据结构传播的过程。冒泡和捕获是事件流在DOM中两种不同的传播方式。
事件流有三个阶段
- 事件捕获阶段
- 处于目标阶段
- 事件冒泡阶段
事件捕获和事件冒泡
事件捕获:事件从最外层父元素到最里层子元素的顺序触发,如document > html > body > div > p。
事件冒泡:事件从最里层子元素到最外层父元素的顺序触发,如p < div < body < html < document。
因为有捕获和冒泡两种传播方式,W3C制定了一个标准可以让我们自己选择使用哪种传播方式。我们在使用addEventListener监听事件时,addEventListener('click',fn,bool) ,如果第三个参数bool不传或者为falsy,那么我们会在冒泡阶段调用fn,如果第三个参数bool为true,那么我们会在捕获阶段调用fn。
target和currentTarget
e.target为用户操作的元素
e.currentTarget是程序员监听的元素
<div>
<span>我是文字</span>
</div>
假设我们监听的是div元素,但用户实际点击的是文字内容,那么
e.target指向span元素
e.currentTarget指向div元素
event.stopPropagation()阻止事件冒泡
当事件使用 event.stopPropagation() 方法将阻止事件冒泡到其父元素,代码示例如下:
<div id="parent" style="width: 200px; height: 200px; border: 1px solid springgreen;">
<div id="son" style="width: 100px; height: 100px; border: 1px solid blue;">son</div>
</div>
<script>
parent.addEventListener('click', () => {
console.log('我是parent');
})
son.addEventListener('click', (e) => {
console.log('我是son');
e.stopPropagation(); // 中断事件冒泡
})
</script>
event.preventDefault()阻止默认事件
如果调用这个方法,默认事件行为将不再触发。什么是默认事件?例如表单一点击提交按钮 submit 跳转页面、 a 标签默认页面跳转或是锚点定位等。
举个例子:
给 a 标签添加点击事件,当用户点击文字就阻止 a 标签的默认页面跳转功能
<a href="https://www.baidu.com" id="x">百度一下</a>
<script>
x.addEventListener('click', (e) => {
e.preventDefault();
})
</script>
二、事件委托
由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方法叫做事件委托。
举个例子:
有一个div元素,div元素里有大量的button按钮,我们需要在点击每个button按钮的时候响应一个事件,怎么做?
<div id="container">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>10</button>
</div>
实现的JS代码:
// 监听父元素 div#container
container.addEventListener('click',(e)=>{
const t = e.target
if(t.matches('button')){
console.log('点击了button')
}
})
思路:
- 首先监听父元素
- 然后根据浏览器传进去的事件信息,拿到当前点击元素e.target
- 再判断当前点击元素是不是button,如果是,就输出log语句
综上所述利用事件委托可以有效减少内存消耗,提高性能。