【JavaScript】从事件流到事件委托
一、DOM事件基础
1. 什么是DOM事件?
DOM事件是用户或浏览器在网页上执行的某种动作,比如点击、鼠标移动、键盘输入等。JavaScript通过事件监听器来响应这些事件。
// 基本事件监听
document.querySelector('myButton').addEventListener('click', function() {console.log('按钮被点击了!');
});
2. 事件的三要素
- 事件源:触发事件的DOM元素
- 事件类型:click、mouseover等
- 事件处理函数:事件触发时执行的函数
二、事件流:捕获与冒泡
1. 事件流的三个阶段
事件流指的是事件完整执行过程中的流动路径
DOM事件流包括三个阶段:
- 捕获阶段:从window对象向下传播到目标元素(中国 陕西 西安)
- 目标阶段:在目标元素上触发
- 冒泡阶段:从目标元素向上传播回window对象(西安 陕西 中国),类比水烧开之前冒的泡泡
2. 代码演示
.father {width: 500px;height: 50px;background-color: pink;}.son {width: 200px;height: 20px;background-color: blue;}
<div class="father"><div class="son"></div>
const father = document.querySelector('.father')const son = document.querySelector('.son')// 在事件执行函数后面加上true变成事件捕获,点击蓝色方块以后弹窗的顺序是爷爷爸爸儿子document.addEventListener('click', function () {alert('我是爷爷')})father.addEventListener('click', function () {alert('我是爸爸')})son.addEventListener('click', function (e) {alert('我是儿子')})
3. 阻止事件冒泡
因为默认有冒泡模式的存在,所有容易导致事件影响父级元素。如果想要把事件限制在当前元素内就需要阻止冒泡,前提是事件冒泡之间需要拿到事件对象此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
使用event.stopPropagation()
方法可以阻止事件继续向上冒泡:
document.getElementById('child').addEventListener('click', function(e) {console.log('子元素点击,阻止冒泡');e.stopPropagation(); // 阻止事件继续向上冒泡
});
4. 阻止冒泡的适用场景
- 模态框点击:点击模态框内部时,阻止事件冒泡到背景层
- 嵌套菜单:子菜单展开时点击子菜单项,阻止触发父菜单的关闭逻辑
- 独立组件:组件内部事件不需要外部感知时
三、事件委托
事件委托是一种利用事件流的特征解决一些开发需求的技巧,可以减少注册次数,提高程序性能。原理
利用了事件冒泡的特点 :给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素的身上,从而触发父元素的事件
3.1 为什么需要事件委托?
传统方式需要为每个元素添加事件监听器,性能低下:
利用事件冒泡机制,只需在父元素上添加一个事件监听器:
// 高效的事件委托
document.querySelector('myList').addEventListener('click', function(e) {if(e.target.tagName === 'LI') {console.log(e.target.textContent);}
});
注意: e.target是我们点击的对象 e.target.tagName是我们点击对象的标签名
3.4 事件委托与冒泡的关系
事件委托完全依赖于事件冒泡机制:
document.querySelector('parent').addEventListener('click', function(e) {const button = e.target.closest('button[data-action]');if(button) {handleAction(button.dataset.action);}
});