ul.addEventListener("click", function (e) {
if (e.target.tagName.toLowerCase() === "li") {
fn(); // 执行某个函数
}
});
但是这种事件委托明显有个缺陷,如果li里面包着span,就无法触发fn。
事件委托的优点:
- 节省监听器
- 实现动态监听
坏处:调试比较复杂,无法确定监听者。
改进前面出现的问题,思路是点击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;
}