手写事件委托
错误版(但是可能能通过面试)
思路:e.target.tagName.toLowerCase === 'li'
ul.addEventListener('click',function (e) {
if(e.target.tagName.toLowerCase() === 'li')){
fn() // 执行某个函数
}
})
bug 在于,如果用户点击的是 li 里面的 span,就没法触发 fn,这显然不对。
好处:
- 节省监听器
- 实现动态监听
坏处:调试比较复杂,不容易确定监听者。
解决坏处:解决不了
高级版
点击 span 后,递归遍历 span 的祖先元素看其中有没有 ul 里面的 li。
思路:
- 声明出发函数 fn
- 监听 ul 点击事件
- while 循环
- 终止条件
!el.matches('li')
el = el.parentNode
- 终止条件
- 调用函数指定参数
el && fn.call(el,e,el)
function fn() {console.log('点击出发')}
ul.addEventListener('click',e=>{
let el = e.target
if(ul === el)return
// 向上递归
while (!el.matches('li')) {
el = el.parentNode
}
el && fn.call(el,e,el) // el:this e:目标 el:元素
}) // 默认为 false