手写事件委托

164 阅读1分钟
ul.addEventListener("click", function (e) {
  if (e.target.tagName.toLowerCase() === "li") {
    fn(); // 执行某个函数
  }
});

但是这种事件委托明显有个缺陷,如果li里面包着span,就无法触发fn。

事件委托的优点:

  1. 节省监听器
  2. 实现动态监听

坏处:调试比较复杂,无法确定监听者。

改进前面出现的问题,思路是点击span后,递归遍历span的祖先元素看其中有没有li,直到ul的时候停下。

function delegate(element, eventType, selector, fn) {
  element.addEventListener(eventType, (e) => {
    let el = e.target;
    while (!el.matches(selector)) {
      if (element === el) {
        el = null;
        break;
      }
      el = el.parentNode;
    }
    el && fn.call(el, e, el);
  });
  return element;
}