事件的传播与委托

184 阅读2分钟

1. 事件传播

    <div id="box1">
        <div id="box2"></div>
    </div> 
    在当前案例中, 点击了 box2 的区域  相当于点击了  box1 内部的空间

    在触发子元素的事件时, 会将行为传播给父级的同类型事件

    触发了子元素的点击事件时, 会将该行为传播给父级,并触发父级的同类型事件
    在传递行为时, 会将行为一直向上传递, 如果父级有同类型事件, 那么触发该事件,如果没有,就一直向上传递

    阻止事件传播
    语法:e.stopPropagation()
    本级不阻止,阻止向上一级传播事件
    <script>
        box1.onclick = function (e) {
                e.stopPropagation() // 阻止事件传播
                console.log('触发了 box1 的点击事件')
        }

        box2.onclick = function () {
                console.log('触发了 box22222 的点击事件')
        }

        box1.oncontextmenu = function () {
                console.log('触发了 box1111111 的右键事件')
        }   

        myBody.onclick = function () {
                console.log('触发了 body 的点击事件')
            }
    </script>

2. 目标冒泡捕获

    window的默认传播方式是冒泡
        传播时 会从目标传播到父级, body, html, document, window
        
    冒泡: 事件传播时, 从目标开始传播, 一直到到父级, body...window
    捕获: 从最顶层开始, 逐层向下传递, 一直到 目标
    
        如果要改为捕获的话这里要用到addEventListener的第三个参数 默认第三个
        参数是false 代表的传播方式是冒泡 
    如果我们想要改变传播方式为捕获,只需要改变第三个参数为true 即可

3. 事件委托

    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>

    获取元素ul
        var myUl = document.querySelector('ul')

    获取元素li 这里获取的是伪数组所以要展开就是...    
        var myLi = [...document.querySelectorAll('li')]

    对第一个li添加点击事件
        myLi[0].onclick = function () {
        console.log('111111111111')
        }
    对第二个li添加点击事件
        myLi[1].onclick = function () {
            console.log('222222222222222')
        }
    对第三个li添加点击事件
        myLi[2].onclick = function () {
        console.log('33333333333333')
        }

    此时页面还没有 第4个li, 所以此处不能这样使用
        myLi[3].onclick = function () {
        console.log('33333333333333')
        }

    此时页面只有 3 个 li, 所以新插入的li没有点击事件
        myLi.forEach(function (item, index) {
            item.onclick = function () {
                console.log(index + 1)
            }
        })
        myUl.onclick = function (e) {
            console.log(e.target, '触发了 ul 的点击事件')
            if (e.target.nodeName === 'LI') {
            console.log('点击了 li')
            }
        }

        创建一个 Li 节点
            var newLi = document.createElement('li')
            newLi.innerText = '我是通过 JS 创建的'

        myUl.appendChild(newLi)


    事件委托
        因为事件冒泡的存在, 所以点击子元素时, 一定会触发给父级
        所以可以将 子元素统一的事件, 都提交给 父级

        e.target: 触发事件的事件源


总结:
    为什么要用事件委托?
    动态的添加了 li 时, 新加的li没有绑定上事件, 需要动态添加完成后重新绑定事
    件, 这样操作比较麻烦所以此时可以利用 事件委托

注:li 的点击事件必须委托给父级的 点击事件

4.阻止默认事件

    <a href="xxx">11111111</a>
        <script>
            var a = document.querySelector('a')
            a.onclick = function (e) 
            {
                return false

            1. 方式1
            console.log('点击了 a 标签, 但是因为有 return false 所以默认的
            跳转功能被拦截')


            2. 通过事件对象拦截      preventDefault()    拦截之后, 取消了 
            a标签的默认跳转功能
            e.preventDefault()
            }
        </script>