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

    对“捕获”和“冒泡”这两个概念,我想我们对冒泡更熟悉一些,因为在我们使用的所有浏览器中,都支持事件冒泡,即事件由子元素向祖先元素传播的,就 像气泡从水底向水面上浮一样。而在像firefox,chrome,safari这类所谓的标准浏览器中,事件传播还有个阶段,那就是捕获阶段,这个很少 有用武之地,所以被人疏忽遗忘也在所难免了,不常用不代表它不存在,本着科学严谨的态度,我们有必要去看一下它的庐山真面目。

    事实上,捕获阶段是一个和冒泡阶段完全相反的过程,即事件由祖先元素向子元素传播,和一个石子儿从水面向水底下沉一样,要说明的是在 IE,opera浏览器中,是不存在这个阶段的。从各浏览器提供的注册事件监听的方法中可见一斑,例如适用于ie,opera的attachEvent, 有两个参数,attachEvent(”on”+type,fn),而适用于所谓标准浏览器的addEventListener则有三个参 数,addEventListener(type,fn,boolean),前面两个参数不用解释,第三个参数boolean,就是决定注册事件发生在捕 获阶段还是冒泡阶段,具体参考如下:

    true : 捕获阶段

    false : 冒泡阶段

    事件分类
    捕获型事件(非IE)、冒泡型事件(所有浏览器都支持)
    捕获型事件是自上而下的,而冒泡型事件是自下而上的。下面我用一个图来直观表示:

     



    冒泡型事件我们在工作中可能会比较多遇到,但捕获型事件怎样才会执行到呢,如果我们想要在非 IE 浏览器中要创建捕获型事件,只需将 addEventListener 的第三个参数设为true就好了。

    DOME:

    <!doctype html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gbk" />
    <title>无标题文档</title>
    <meta name="description" content="" />
    <meta name="keywords" content="" />
    </head>
    
    <body>
    <style type="text/css">
    *{margin:0;padding:0;}
    h1{text-align:center;color:#666;margin-top:18px;}
    #content{width:700px;height:250px;border:5px solid green;margin:20px auto;position:relative;}
    #obj1{height:100px;background:#d5d5d5;}
    #obj2{background:#777;}
    #obj3{position:absolute;top:200px;left:150px;width:200px;background:#555;}
    #obj4{height:100px;background:#999;margin-top:50px;}
    .active{color:#f00;}
    </style>
    <h1>悟透事件的捕获和冒泡</h1>
    <div id="content">
        <div id="obj1">
            <h2>元素a</h2>
            <div id="obj2">
                <h2>元素b</h2>
                <div id="obj3">
                    <h2>元素c</h2>
                </div>
            </div>
        </div>
    
        <div id="obj4">
            <h2>元素d</h2>
        </div>
    </div>
    
    <script type="text/javascript"> 
        var divs = document.getElementById("content").getElementsByTagName("div");
        var count = 1;
        for(var i=0;i<divs.length;i++){
            bindEvent(divs[i],"click",function(){
                var obj = document.createTextNode("->"+count++);
                this.getElementsByTagName("h2")[0].insertBefore(obj,null);
                this.className = "active";
            });
        }
        
        //取消事件冒泡
        function stopBubble(e){
            e = e||window.event;
            if(e.stopPropagation){
                e.stopPropagation();
            }else{
                e.cancelBubble = true;
            }
        }
    
        //绑定事件
        function bindEvent(elem,type,fn){
            if(elem.attachEvent){
                var typeRef = "_" + type;
                if(!elem[typeRef]){
                    elem[typeRef] = [];
                }
                for(var i in elem[typeRef]){
                    if(elem[typeRef][i] == fn){
                        return;
                    }
                }
                elem[typeRef].push(fn);
                elem["on"+type] = function(){
                    for(var i in this[typeRef]){
                        this[typeRef][i].apply(this,arguments);
                    }
                }    
            }else{
                elem.addEventListener(type,fn,false);
            }
        }
    
        //移除事件绑定
        function removeEvent(elem,type,fn){
            if(elem.detachEvent){
                if(elem["_"+type]){
                    for(var i in elem["_"+type]){
                        if(elem["_"+type][i] == fn){
                            elem["_"+type].splice(i,1);
                            break;
                        }
                    }
                }
            }else{
                elem.removeEventListener(type,fn,false);
            }
        }
    </script>    
    </body>
    </html>

    取消事件冒泡:

    在默认情况下,发生在一个子元素上的单击事件(或者其他事件),如果在其父级元素绑定了一个同样的事件,此时点击子元素,click事件会首先被子元素捕获,执行绑定的事件程序,之后会被父级元素捕获,再次激发一段脚本的执行,这就是所谓的“事件冒泡”。

    在通常情况下,我们只希望事件发生在它的目标而并非它的父级元素上,只需加个stopBubble方法,即可取消事件冒泡,详见以下代码:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>无标题文档</title>
    <style type="text/css">
    *{ margin:0; padding:0;}
    </style>
    </head>
    <body>
    <div id="obj1" style=" 500px; height:500px; background:#000;">
        <div id="obj2" style="400px; height:400px; background:red;"></div>
    </div>
    <script type="text/javascript">
        //阻止事件冒泡的通用函数
        function stopBubble(e){
            // 如果传入了事件对象,那么就是非ie浏览器
            if(e&&e.stopPropagation){
                //因此它支持W3C的stopPropagation()方法
                e.stopPropagation();
            }else{
                //否则我们使用ie的方法来取消事件冒泡
                window.event.cancelBubble = true;
            }
        }
    
        var obj1 = document.getElementById('obj1');
        var obj2 = document.getElementById('obj2');
        obj1.onclick = function(){
            alert('我点击了obj1');
        }
        obj2.onclick = function(e){
            alert('我点击了obj2');
            stopBubble(e);
        }
    </script>
    </body>
    </html>

    现在你可能想知道,什么时候需要阻止事件冒泡?事实上,现在绝大多数情况下都可以不必在意它。但是当你开始开发动态应用程序(尤其是需要处理键盘和鼠标)的时候,就有这个必要了。

  • 相关阅读:
    php图片水印添加,压缩,剪切的封装类
    使用观察者模式处理异常信息
    php中的错误级别
    php 递归函数的三种实现方式
    php利用递归函数实现无限级分类
    利用http协议发布博客园博文评论
    结合php ob函数理解缓冲机制
    php 正则表达式捕获组与非捕获组
    php 利用socket发送GET,POST请求
    php mysqli扩展之预处理
  • 原文地址:https://www.cnblogs.com/macliu/p/4320687.html
Copyright © 2011-2022 走看看