js delegate 实现
事件委托的实现原理
事件委托利用事件冒泡机制,将事件监听器绑定在父元素而非每个子元素上。当子元素触发事件时,事件会冒泡到父元素,通过判断事件目标(event.target)来执行对应逻辑。
基本实现方式
document.getElementById('parent').addEventListener('click', function(event) {
if (event.target.matches('.child')) {
// 处理子元素的点击事件
console.log('Child element clicked:', event.target);
}
});
动态元素处理优势
事件委托特别适合动态添加的元素,无需重新绑定事件监听器。新添加的子元素自动继承父元素的事件处理逻辑。
// 动态添加元素仍可触发事件
const newChild = document.createElement('div');
newChild.className = 'child';
newChild.textContent = 'New Child';
document.getElementById('parent').appendChild(newChild);
多级委托实现
对于嵌套结构,可通过closest()方法向上查找匹配元素。

document.addEventListener('click', function(event) {
const target = event.target.closest('.delegated-item');
if (target) {
console.log('Delegated item clicked:', target);
}
});
性能优化建议
- 尽量选择最近的公共父元素进行委托,减少事件冒泡路径
- 复杂选择器使用
matches()方法前先进行简单判断 - 避免在document级别绑定过多委托事件
实际应用示例
// 表格行点击委托示例
document.querySelector('table').addEventListener('click', (e) => {
const row = e.target.closest('tr[data-id]');
if (!row) return;
const id = row.dataset.id;
console.log('Selected row ID:', id);
});
// 按钮组委托示例
const buttonActions = {
save: () => console.log('Saving...'),
delete: () => console.log('Deleting...')
};
document.querySelector('.toolbar').addEventListener('click', (e) => {
const action = e.target.dataset.action;
if (action && buttonActions[action]) {
buttonActions[action]();
}
});
注意事项
- 某些事件(如focus/blur)不冒泡,需使用focusin/focusout替代
- 鼠标移动相关事件在密集触发时需考虑性能影响
- 阻止事件冒泡会导致委托失效
- 移动端触摸事件需额外处理touchstart/touchend






