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=" width:500px; height:500px; background:#000;">
    <div id="obj2" style="width: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>

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

时间: 2024-10-07 08:18:48

javascript事件捕获与冒泡的相关文章

你根本不懂Javascript(5): HTML事件捕获与冒泡

本文最初发布于http://szhshp.org转载请注明 事件捕捉与冒泡 先捕获的必然是父节点, 然后一层层向下捕获, 然后一层层向上冒泡 这里是一个td被点击的效果图 通过三个阶段: 捕捉阶段: 从父节点, 逐渐向目标节点冒泡, 即自上向下 接近目标elem阶段(这一阶段会同时激活第一阶段和第三阶段的handler) 冒泡阶段: 从子节点向父节点冒泡 事件绑定机制 onXXX(event) addEventListener(event, handler) jQuery的elem.on(eve

javascript -- 事件捕获,事件冒泡

使用js的时候,当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,单击子元素时,父元素的onclick事件也会被触发.js里称这种事件连续发生的机制为事件冒泡或者事件捕获. 为什么会有事件冒泡,又有捕获呢?应为当初IE浏览器和Natscape浏览器分别对自己浏览器的事件采用了不同的发生机制,IE浏览器采用了冒泡型:定义有相同事件的嵌套元素,当事件被触发时,子元素拥有优先权,即从里向外发生,像水里的泡泡一样从里向外冒.而Netscape采用了相反的做法,即捕获型,父元素拥有优先权

javascript——事件捕获冒泡

事件冒泡:obj.addEventListener(eventType ,fn ,false); false => 冒泡(出来) 事件捕获:obj.addEventListener(eventType ,fn ,true); true => 捕获(进去) HTML部分: <div id="div1"> div1 <div id="div2"> div2 <div id="div3">div3<

事件捕获和冒泡

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Monaco; color: #2b7ec3 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Monaco; color: #d74200 } p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Monaco; color: #4f5d66 } p.p4 { margin: 0

事件捕获与冒泡的再探

先看一段代码,猜猜输出结果 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="id1" style="width: 200px;height:200px;border

事件捕获、冒泡、绑定、赋值、委托、兼容、滚轮

clientX/Y           可视区的鼠标坐标                  全兼容 offsetX/Y           鼠标坐标到物体边框的距离    IE+Chrome pageX/Y             页面                                    高级 浏览器 screenX/Y           屏幕                                    全兼容(没用) var e =  evt || window.

Js事件捕获和冒泡

昨天有个面试官问我的问题,他直接问我两个DIV嵌套,都有click事件,单击的时候先弹出子DIV还是父DIV.完全不知所以然. 过后经过查询资料后,很是惭愧.原来他问的就是关于JS捕获和冒泡的. 我查询了一些资料: 事件捕获(父--> 子) 当你使用事件捕获时,父级元素先触发,子级元素后触发,即div先触发,p后触发. 事件冒泡(子--> 父) 当你使用事件冒泡时,子级元素先触发,父级元素后触发,即p先触发,div后触发. W3C模型 W3C模型是将两者进行中和,在W3C模型中,任何事件发生时

js中addEventListener第三个参数涉及到的事件捕获与冒泡

js中,我们可以给一个dom对象添加监听事件,函数就是 addEventListener("click",function(){},true); 很容易理解,第一个参数是事件类型,比如点击(click).触摸(touchstart), 第二个参数就是事件函数, 比如我给一个button添加alert函数. window.onload=function(){ document.getElementById("hello").addEventListener("

JS中的事件顺序(事件捕获与冒泡)

问题 如果一个元素和它的祖先元素注册了同一类型的事件函数(例如点击等), 那么当事件发生时事件函数调用的顺序是什么呢? 比如, 考虑如下嵌套的元素: ----------------------------------- | outer | | ------------------------- | | |inner | | | ------------------------- | | | ----------------------------------- 两个元素都有onclick的处理