zoukankan      html  css  js  c++  java
  • js事件(事件冒泡与事件捕获)

    事件冒泡事件捕获分别由微软网景公司提出,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题。

    <div id='aa' click='po'>
            <p id='bb' click='on'>点击</p>
    </div>
    

      上面两个点击事件如果点击的时候,到底谁会被先触发呢,为了解决这个问题微软和网景提出了两种几乎完全相反的概念。

    事件冒泡

    微软提出了名为事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。

    因此在事件冒泡的概念下在p元素上发生click事件的顺序应该是p -> div -> body -> html -> document

    事件捕获

    网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。

    因此在事件捕获的概念下在p元素上发生click事件的顺序应该是document -> html -> body -> div -> p

    后来 w3c 采用折中的方式,平息了战火,制定了统一的标准——先捕获再冒泡

    冒泡的案例

    <div id="s1">s1
        <div id="s2">s2</div>
    </div>
    <script>
        s1.addEventListener("click",function(e){
            console.log("s1 冒泡事件");
        },false);
        s2.addEventListener("click",function(e){
            console.log("s2 冒泡事件");
        },false);
    </script>
    

      

    捕获的案例

    <div id="s1">s1
        <div id="s2">s2</div>
    </div>
    <script>
        s1.addEventListener("click",function(e){
            console.log("s1 捕获事件");
        },true);
        s2.addEventListener("click",function(e){
            console.log("s2 捕获事件");
        },true);
    </script>
    

      当事件冒泡和捕获在一起出现的时候

    <div id="s1">s1
        <div id="s2">s2</div>
    </div>
    <script>
    s1.addEventListener("click",function(e){
            console.log("s1 冒泡事件");         
    },false);
    s2.addEventListener("click",function(e){
            console.log("s2 冒泡事件");
    },false);
            
    s1.addEventListener("click",function(e){
            console.log("s1 捕获事件");
    },true);
            
    s2.addEventListener("click",function(e){
            console.log("s2 捕获事件");
    },true);
    </script>
    

      

    • 对于非被点击dom节点则先执行捕获在执行冒泡

    • 对于被点击的dom节点则是先执行先注册的事件,无论冒泡还是捕获

    事件冒泡和捕获,衍生出事件委托,因为当你点击子元素的时候,实际上走的是父组件的事件

    <ul id="list">
        <li>111</li>
        <li>2222</li>
    </ul>
    

      点击子元素的时候,由父元素去代为执行,能减少事件输出,代码的编写量

    取消默认事件

    w3c 的方法是 e.preventDefault(),IE 则是使用 e.returnValue = false;

    取消默认事件,还可以用return来进行阻止

    阻止冒泡的事件

    w3c 的方法是 e.stopPropagation(),IE 则是使用 e.cancelBubble = true

    IE9 之前的IE不支持 stopPropagation() 方法。相反,IE事件对象有一个 cancleBubble 属性,设置这个属性为 true 能阻止事件进一步传播。( IE8 及之前版本不支持事件传播的捕获阶段,所以冒泡是唯一待取消的事件传播。)

    冒泡事件案例:

    <div id='div' onclick='alert("div");'>
    <ul onclick='alert("ul");'>
    <li onclick='alert("li");'>test</li>
    </ul>
    </div>
    

      正常情况下,li>ul>div,这就是正常的冒泡的事件

    阻止冒泡的事件:

    window.event? window.event.cancelBubble = true : e.stopPropagation();
    

      阻止冒泡事件,案例

    <html>
        <head>
            <style>
                #a{
                     300px;
                    height: 300px;
                    background: pink;
                }
                #b{
                     200px;
                    height: 200px;
                    background: blue;
                }
                #c{
                     100px;
                    height: 100px;
                    background: yellow;
                }
            </style>
        </head>
        <body>
            
            <div id="a">
                <div id="b">
                    <div id="c"></div>
                </div>
            </div>
            <script>
                var a = document.getElementById("a"),
                    b = document.getElementById("b"),
                    c = document.getElementById("c");
                c.addEventListener("click", function (event) {
                    console.log("c1");
                    event.stopImmediatePropagation();
                    // 注意第三个参数没有传进 false , 因为默认传进来的是 false
                    //,代表冒泡阶段调用,个人认为处于目标阶段也会调用的
                });
                c.addEventListener("click", function (event) {
                    console.log("c2");
                }, true);
                b.addEventListener("click", function (event) {
                    console.log("b");
                }, true);
                a.addEventListener("click", function (event) {
                    console.log("a1");
                }, true);
                a.addEventListener("click", function (event) {
                    console.log("a2")
                });
                a.addEventListener("click", function (event) {
                    console.log("a3");
                    event.stopImmediatePropagation();
                }, true);
                a.addEventListener("click", function (event) {
                    console.log("a4");
                }, true);
            </script>
        </body>
    </html>

    当时写博客的时候忘了写阻止冒泡的事件了,多谢老铁提醒!!!

  • 相关阅读:
    3、excel—如何把相同年月日的中相同的数据相加
    Linux_plsql通过跳板的ssh隧道访问oracle1521(转)
    微信小程序-歌词滚动实现
    微信小程序-RSA 加解密
    如何给开源仓库贡献代码
    linux开发调试常用命令-gdb
    vector 内存分配和释放
    Ubuntu上SmartGit三十天试用到期解决办法
    Django-325版本创建时候需要手动设置的内容
    Django 博客园练习--待完成
  • 原文地址:https://www.cnblogs.com/yishifuping/p/10304087.html
Copyright © 2011-2022 走看看