手写事件委托

63 阅读1分钟

基础版本

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta
            name="viewport"
            content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            * {
                list-style: none;
            }
            ul {
                width: 800px;
                height: 600px;
                border: 1px solid #000;
            }
            ul li {
                width: 600px;
                height: 400px;
                border: 1px solid #000;
            }
            ul li p {
                width: 400px;
                height: 100px;
                border: 1px solid #000;
            }
            ul li div {
                width: 400px;
                height: 100px;
                border: 1px solid #000;
            }
        </style>
    </head>
    <body>
        <ul>
            ul
            <li>
                li
                <p>p</p>
                <div>div</div>
            </li>
        </ul>
        <script>
            let ul = document.querySelector('ul')
            ul.addEventListener('click', e => {
               if (e.target.tagName.toLowerCase() === 'li') {
                    console.log('执行和li相关的操作')
                }
           })
        </script>
    </body>
</html>

点击li之后的效果 image.png

点击p之后的效果 image.png

进阶版本

基础版本有个问题,如果点击了li的子元素就不会正常触发了,进阶的思路是一直找其父元素,看是不是li直到ul为止

ul.addEventListener("click",e=>{
    let curElement = e.target
    while(!curElement.matches("li")){
        if(ul === curElement){
            curElement = null
            break
        }
        curElement = curElement.parentNode
    }
    curElement && console.log("执行和li相关的操作")
})

// 封装成函数版本
const delegate = (element,type,selector,fn) =>{
    element.addEventListener(type,e=>{
        let curElement = e.target
        while(!curElement.matches(selector)){
            if(element === curElement){
                curElement = null
                break
            }
            curElement = curElement.parentNode
        }
        curElement && fn.call(curElement,e)
    })
}
deletage(ul,"click","li",()=>{
    console.log("执行和li相关的操作")
})

点击li之后的效果 image.png

点击p之后的效果 image.png