一、以给ul元素添加click事件为例
<body>
<ul id="x1">
子元素1
<li>li元素<span>span元素</span></li>
子元素2
<li>li元素<span>span元素</span></li>
子元素3
<li>li元素<span>span元素</span></li>
</ul>
</body>
<script>
let ul = document.getElementById('x1')
ul.addEventListener('click', e => {
if(e.target.tagName.toLowerCase() == 'li') {
console.log('打印');
}
})
</script>
// 存在一个问题 span元素的点击事件并不会上浮到li元素
// 也就是点击span元素 不会输出'打印'
二、事件委托升级版
<body>
<ul id="x2">
子元素1
<li>li元素<span>span元素</span></li>
子元素2
<li>li元素<span>span元素</span></li>
子元素3
<li>li元素<span>span元素</span></li>
</ul>
</body>
<script>
function delegate(element, event, fn) {
element.addEventListener(event, e => {
const current = e.target
if(element.contains(current)) fn.call()
})
}
let ul2 = document.getElementById('x2')
delegate(ul2, 'click', () => {
console.log('打印');
})
</script>
// 点击li元素和span元素都会输出 '打印'
三、完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>测试1</h1>
<ul id="x1">
子元素1
<li>li元素<span>span元素</span></li>
子元素2
<li>li元素<span>span元素</span></li>
子元素3
<li>li元素<span>span元素</span></li>
</ul>
<h1>测试2</h1>
<ul id="x2">
子元素1
<li>li元素<span>span元素</span></li>
子元素2
<li>li元素<span>span元素</span></li>
子元素3
<li>li元素<span>span元素</span></li>
</body>
<script>
let ul1 = document.getElementById('x1')
ul1.addEventListener('click', e => {
if(e.target.tagName.toLowerCase() == 'li') {
console.log('打印');
}
})
function delegate(element, event, fn) {
element.addEventListener(event, e => {
const current = e.target
if(element.contains(current)) fn.call()
})
}
let ul2 = document.getElementById('x2')
delegate(ul2, 'click', () => {
console.log('打印');
})
</script>
</html>