js中的事件,冒泡与捕获,开关案例

158 阅读2分钟

事件传播

在当前案例中, 点击了box2的区域相当于点击了box1内部的空间
    在触发子元素的事件时, 会将 行为 传播给父级的同类型事件
    触发了子元素的点击事件时, 会将该行为传播给父级, 
    并 触发父级的同类型事件
    
    在传递行为时, 会将行为一直向上传递, 如果父级有同类型事件, 那么触发该事件
    如果没有, 则继续往上传递
    
    阻止事件传播: e.stopPropagation()

<style>
    #box1 {
        width: 500px;
        height: 500px;
        background-color: pink;
    }

    #box2 {
        width: 200px;
        height: 200px;
        background-color: green;
    }
</style>

<div id="box1">
    <div id="box2"></div>
</div>

var box1 = document.getElementById('box1')
var box2 = document.getElementById('box2')
var myBody = document.body

box1.onclick = function (e) {
    e.stopPropagation() // 阻止事件传播
    console.log('触发了 box1 的点击事件')
}

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

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

目标冒泡捕获

目标: 目标就是事件源
    传播时会从目标传播到父级,body,html,document,window
    window默认的传播方式为冒泡
    冒泡: 事件传播时, 从目标开始传播, 一直到到父级,body...window
    捕获: 从最顶层开始, 逐层向下传递, 一直到目标

捕获的话需要传递第三个参数为,true
    addEventListener 第三个参数 默认值 为 false 代表传播方式 为 冒泡
    如果想改变传播方式为 捕获, 那么需要 将第三个参数传递为 true
    box1.addEventListener('click', function () {
        console.log('触发了 box1 的点击事件')
    }, true)
    box2.addEventListener('click', function () {
        console.log('触发了 box2 的点击事件')
    }, true)
    myBody.addEventListener('click', function () {
        console.log('触发了 body 的点击事件')
    }, true)

    //触发了 body 的点击事件,触发了 box1 的点击事件,触发了 box2222 的点击事件

事件委托

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

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

阻止默认事件

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

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

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

开关案例

<button>点击获取验证码</button>
<script>
    var btn = document.querySelector('button')

    var flag = true

    // 1. 给按钮添加点击事件
    btn.onclick = function () {
        // 1.0 添加开关判断, 为false的时候禁止执行函数
        if (!flag) return

        // 1.1 声明一个变量, 用于文本的替换
        var count = 5
        // 1.2 给按钮一个新的文本
        btn.innerText = `${count} S后可以重新点击`
        // 1.3 关闭开关, 在定时器结束之前让其不能重复执行代码
        flag = false

        // 1.4 开启定时器
        var timer = setInterval(function () {
            // 1.5 修改变量后重新赋值
            count--
            btn.innerText = `${count} S后可以重新点击`
            
            // 1.6 当滚定时间到达后结束定时器并重新打开开关, 让函数可以二次调用
            if (count == 0) {
                flag = true
                btn.innerText = `点击获取验证码`
                clearInterval(timer)
            }
        }, 1000)
    }
</script>