{T}

代理

下面的 HTML 代码是一个简单的无序列表,希望点击每个项目的时候调用 getInfo() 函数,当点击“编辑” 时,调用一个 edit() 函数,当点击 “删除” 时,调用一个 del() 函数

要实现这个功能并不难,只需要对列表中每一项,分别监听 3 个元素的 click 事件即可

html
<ul> 
	<li>项目1<span>编辑</span><span>删除</span></li> 
	<li>项目2<span>编辑</span><span >删除</span></li> 
	<li>项目3<span>编辑</span><span>删除</span></li> 
</ul>

但如果数据量一旦增大,事件绑定占用的内存以及执行时间将会成线性增加,而其实这些事件监听函数逻辑一致,只是参数不同而已。此时可以用 事件代理事件委托 来进行优化。不过在此之前,我们必须先复习一下 DOM 事件的触发流程

事件触发流程主要分为 3 个阶段:

  • 捕获 事件对象 Window 传播到目标的父对象

  • 目标 事件对象到达事件对象的事件目标

  • 冒泡 事件对象从目标的父节点开始传播到 Window

事件代理的实现原理就是利用 DOM 事件的触发流程来对一类事件进行统一处理。比如对于上面的列表,在 ul 元素上绑定事件统一处理,通过得到的事件对象来获取参数,调用对应的函数

javascript
const ul = document.querySelector('.list')
ul.addEventListener('click', e => {
  const t = e.target || e.srcElement
  if (t.classList.contains('item')) {
    getInfo(t.id)
  } else {
    id = t.parentElement.id
    if (t.classList.contains('edit')) {
      edit(id)
    } else if (t.classList.contains('delete')) {
      del(id)
    }
  }
})

这里选择默认在冒泡阶段监听事件,但和捕获阶段监听并没有区别。对于其他情况还需要具体情况具体细分析,比如有些列表项目需要在目标阶段进行一些预处理操作,那么可以选择冒泡阶段进行事件代理