JavaScript实现一个简单的事件委托

47 阅读1分钟

一、以给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>