美文网首页
事件捕获、冒泡和代理

事件捕获、冒泡和代理

作者: 笑该动人d | 来源:发表于2020-09-02 17:01 被阅读0次

一、JS事件介绍

JS事件捕获和事件冒泡原型
事件绑定的方式
  • 直接绑定在dom上
<div onclick="fun();">click</div>
  • 使用onclick
document.getElementById("xxx").onclick = function(){
    ...
};
  • 使用推荐的标准模式
document.getElementById("xxx").addEventListener("click",function(e){
    ...
});

二、事件冒泡

当一个元素的事件触发了,同样的事件会在该元素的所有祖辈元素中触发一次,事件冒泡(从里往外);事件冒泡为默认事件

1.示例

  • html
<ul>
    <li>
        <p>
            <a href="#">a元素</a>
        </p>
    </li>
</ul>
  • js
window.onload = function(){
    const ulEle = document.querySelector("ul");
    const liEle = document.querySelector("li");
    const pEle = document.querySelector("p");
    const aEle = document.querySelector("a");

    ulEle.onclick = function(){
        console.log("ul 点击事件");
    }
    liEle.onclick = function(){
        console.log("liEle 点击事件");
    }
    pEle.onclick = function(){
        console.log("pEle 点击事件");
    }
    aEle.onclick = function(){
        console.log("aEle 点击事件");
    }
}
  • 点击a元素内容后,打印结果如下
    事件会从a标签开始往外冒泡执行,事件冒泡为默认执行的事件流; a -> p -> li -> ul

2. 用addEventListener()绑定事件

在用addEventListener()方法绑定事件的时候,有三个参数:

  • 第一个参数是 事件,click表示点击事件
  • 第二个参数是 function,为该事件触发后执行的代码
  • 第三个参数是true|false,是解释该方法是在冒泡流事件上还是捕获流事件上true的话会捕获进来时的(外->内),false的话会捕获出去时的(内->外)
window.onload = function(){
    const ulEle = document.querySelector("ul");
    const liEle = document.querySelector("li");
    const pEle = document.querySelector("p");
    const aEle = document.querySelector("a");

        ulEle.addEventListener("click",function(){
            console.log("ul 点击事件");
        },false);   
        liEle.addEventListener("click",function(){
            console.log("liEle 点击事件");
        },false);   
        pEle.addEventListener("click",function(){
            console.log("pEle 点击事件");
        },true);   
        aEle.addEventListener("click",function(){
            console.log("aEle 点击事件");
        },true);   
}
设置了点击事件的事件流之后,打印结果如下
  • 设置了事件流之后,事件的默认事件流就不是冒泡了,而是按照truefalse设置的事件流依次执行,先判断为true的捕获,再冒泡 p -> a -> li -> ul
    image.png

三、事件捕获

上面了解到addEventListener()方法中定义第三个参数为true时,会执行捕获流(外 -> 内),所以事件捕获也就很简单了,如下代码
ulEle.addEventListener("click", function (e) {
    console.log("ul 被点击");
}, true)

liEle.addEventListener("click", function () {
    console.log("liEle 被点击");
}, true)

pEle.addEventListener("click", function () {
    console.log("pEle 被点击");
}, true)

aEle.addEventListener("click", function () {
    console.log("aEle 被点击");
}, true)
  • 打印结果


四、事件代理(事件委托)

在实际的开发过程中,根据事件冒泡的原理,我们可以用一种叫做事件代理的方法,也叫事件委托
  • 应用场景
    在一个ul列表中有很多项数据,每一项数据都一个点击事件,在不知道数据有多少的时候,不能每一个数据项都设置一个点击事件,我们就可以把所有的点击事件都委托给他们公共的代理节点,让代理去操作执行点击事件,而我们则需要做的是去判断当前点击的按钮是否是当前我们需要点击的按钮
示例:当点击按钮的时候,显示按钮对应的标题

完整代码如下

<body>
    <div>
        <ul class="ul">
            <li>
                <h4>标题1</h4>
                <p>按钮1</p>
            </li>
            <li>
                <h4>标题2</h4>
                <p>按钮2</p>
            </li>
            <li>
                <h4>标题3</h4>
                <p>按钮3</p>
            </li>
            <li>
                <h4>标题4</h4>
                <p>按钮4</p>
            </li>
        </ul>
    </div>

    <script>
        window.onload = function(){
            // 获取代理节点
            const ulEle = document.querySelector(".ul");

            ulEle.addEventListener("click", function(event){
                // 获取事件对象(兼容性写法)
                const ev = event || window.event;
                // 获取darget
                const target = ev.target || event.srcElement;
                // 判断点击的标签是不是p标签, toLowerCase() 方法将字符变成小写
                if(target.nodeName.toLowerCase() == 'p'){
                    // previousElementSibling 获取当前节点的上一个兄弟节点
                    const titleEle = target.previousElementSibling;
                    console.log("当前点击的按钮对应的文本标题是:",titleEle.innerHTML);
                }
            })
        }
    </script>
</body>
  • 打印结果
    点击按钮1的时候打印的内容为按钮1 对应的标题


相关文章

网友评论

      本文标题:事件捕获、冒泡和代理

      本文链接:https://www.haomeiwen.com/subject/hsmstktx.html