事件委托
事件委托(事件代理)是将事件监听器绑定在父元素上,利用事件冒泡统一处理子元素事件的技术。
核心原理
利用事件冒泡:子元素事件会冒泡到父元素,通过 event.target 判断具体触发元素。
JavaScript
// 不使用事件委托:每个li都绑定事件
document.querySelectorAll('li').forEach(li => {
li.addEventListener('click', handler);
});
// 使用事件委托:只在父元素绑定一个事件
ul.addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
console.log(e.target.textContent);
}
});
基本用法
判断目标元素
JavaScript
ul.addEventListener('click', (e) => {
// 判断点击的是li元素
if (e.target.tagName === 'LI') {
e.target.classList.toggle('active');
}
});
matches方法
使用CSS选择器匹配:
JavaScript
ul.addEventListener('click', (e) => {
if (e.target.matches('.item')) {
console.log('点击了item');
}
});
closest方法
处理嵌套结构:
JavaScript
ul.addEventListener('click', (e) => {
const li = e.target.closest('li');
if (li && ul.contains(li)) {
console.log(li.textContent);
}
});
适用场景
动态添加的元素
JavaScript
// 新添加的li自动拥有点击事件
ul.addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
console.log(e.target.textContent);
}
});
// 动态添加
const li = document.createElement('li');
ul.appendChild(li); // 无需单独绑定事件
大量相似元素
JavaScript
// 1000个单元格,只绑定一个事件
table.addEventListener('click', (e) => {
if (e.target.tagName === 'TD') {
console.log('单元格被点击');
}
});
统一管理事件
JavaScript
// 通过data属性区分不同操作
list.addEventListener('click', (e) => {
const action = e.target.dataset.action;
switch(action) {
case 'edit':
editItem(e.target);
break;
case 'delete':
deleteItem(e.target);
break;
}
});
优缺点对比
| 优点 | 缺点 |
|---|---|
| 减少内存占用 | 需要判断target |
| 动态元素自动绑定 | 不支持不冒泡事件 |
| 代码简洁 | 层级嵌套判断复杂 |
注意:
focus、blur等事件不冒泡,需用focusin、focusout替代。
完整示例
JavaScript
// HTML结构
// <ul id="list">
// <li data-id="1">项目1 <button data-action="delete">删除</button></li>
// </ul>
document.getElementById('list').addEventListener('click', (e) => {
const action = e.target.dataset.action;
if (action === 'delete') {
const li = e.target.closest('li');
li.remove();
return;
}
const li = e.target.closest('li');
if (li) {
console.log('选中:', li.dataset.id);
}
});
要点总结
- 事件委托利用事件冒泡,在父元素统一处理
- 通过
e.target或e.target.closest()判断目标元素 - 动态添加的元素无需重新绑定事件
- 大量元素时显著减少内存占用
- 不冒泡事件(如focus/blur)无法使用委托
📝 发现内容有误?点击此处直接编辑