JS事件传播机制浅析(事件捕获与事件冒泡)

很久以来一直对js事件传播机制搞的一塌糊涂,项目中用到时去各种度娘顾狗,虽也能做出产品,但总不能熟记于心。今日姑且做个demo加深记忆。

 

W3C标准的JS事件传播包含事件捕获和事件冒泡,而非标准的JS事件传播(IE)则只支持事件冒泡。下面就从W3C的标准事件传播开始说:

 

事件的传播是从事件捕获开始的,到达目标dom 节点(绑定相关事件句柄的dom节点) 后,执行相关的事件句柄,然后开始冒泡回传。事件捕获是从dom根节点(document)开始一层层的往子节点的方向捕获,直到捕获到相关事件句柄,而事件冒泡是从当前节点往父节点方向冒泡传播的。

 

W3C 支持事件捕获的事件绑定方法:addEventListener(type,fn,useCapture); useCapture就是用来设置是否支持事件捕获的参数。阻止事件传播可以用e.stopPropagation();一旦调用的stopPropagation事件传播将会被阻断,不会按着既定的方向继续传播了。

下边举一系列的例子:

#1全部阻止事件捕获

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
    <div id="child" style="padding:100px;border:1px solid #333333;">
        <div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
    </div>
</div>

<script>
    var $=function(id){
        return document.getElementById(id);
    };
    function alertP(e){
        alert("Parent");
    }
    function alertC(){
        alert("Child");
    }
    function alertG(e){
        alert("Grandson");
     
    }
    $("parent").addEventListener("click",alertP,false);
    $("child").addEventListener("click",alertC,false);
    $("grandson").addEventListener("click",alertG,false);
</script>
</body>
</html>

点击最里层的div,弹出的内容顺序是:

Grandson,Child,Parent

因为我们这里把useCapture都设置成了false,就是意味着不要应用事件捕获的过程,直接冒泡。事件是从最里层向最外层(子-》父)冒泡的。


#2全部支持事件捕获
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
    <div id="child" style="padding:100px;border:1px solid #333333;">
        <div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
    </div>
</div>

<script>
    var $=function(id){
        return document.getElementById(id);
    };
    function alertP(e){
        alert("Parent");
    }
    function alertC(){
        alert("Child");
    }
    function alertG(e){
        alert("Grandson");
      
    }
    $("parent").addEventListener("click",alertP,true);
    $("child").addEventListener("click",alertC,true);
    $("grandson").addEventListener("click",alertG,true);
</script>
</body>
</html>

 

点击最里层的div,弹出的内容顺序是:

Parent,Child,Grandson
这是因为useCapture设为true,意味着支持事件捕获,事件捕获是从父节点往子节点方向开始捕获的。


#3.部分支持事件捕获

 

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
    <div id="child" style="padding:100px;border:1px solid #333333;">
        <div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
    </div>
</div>

<script>
    var $=function(id){
        return document.getElementById(id);
    };
    function alertP(e){
        alert("Parent");
    }
    function alertC(){
        alert("Child");
    }
    function alertG(e){
        alert("Grandson");
    }
    $("parent").addEventListener("click",alertP,false);
    $("child").addEventListener("click",alertC,true);
    $("grandson").addEventListener("click",alertG,false);
</script>
</body>
</html>

 

点击最里层的div,弹出的内容顺序是:

Child,Grandson,Parent;
#4.阻断事件传播

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
    <div id="child" style="padding:100px;border:1px solid #333333;">
        <div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
    </div>
</div>

<script>
    var $=function(id){
        return document.getElementById(id);
    };
    function alertP(e){
        alert("Parent");
    }
    function alertC(){
        alert("Child");
    }
    function alertG(e){
        alert("Grandson");
        e.stopPropagation();
    }
    $("parent").addEventListener("click",alertP,false);
    $("child").addEventListener("click",alertC,true);
    $("grandson").addEventListener("click",alertG,false);
</script>
</body>
</html>

  

点击最里层的div,弹出的内容顺序是:

Child,Grandson;

这里是冒泡的过程被阻断的;


#5.这个阻断多次一举
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
    <div id="child" style="padding:100px;border:1px solid #333333;">
        <div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
    </div>
</div>

<script>
    var $=function(id){
        return document.getElementById(id);
    };
    function alertP(e){
        alert("parent");
        e.preventDefault();

    }
    function alertC(){
        alert("Child");
        e.stopPropagation();
    }
    function alertG(e){
        alert("Grandson");
    }
//    $("parent").onclick=alertP;
//    $("child").onclick=alertC;
//    $("grandson").onclick=alertG;
    $("parent").addEventListener("click",alertP,true);
    $("child").addEventListener("click",alertC,false);
    $("grandson").addEventListener("click",alertG,true);
</script>
</body>
</html>

点击最里层的div,弹出的内容顺序是:

Parent,Grandson,Child;

#6.阻止捕获和阻断传播混用
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
    <div id="child" style="padding:100px;border:1px solid #333333;">
        <div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
    </div>
</div>

<script>
    var $=function(id){
        return document.getElementById(id);
    };
    function alertP(e){
        alert("parent");
        e.preventDefault();

    }
    function alertC(){
        alert("Child");

    }
    function alertG(e){
        alert("Grandson");
        e.stopPropagation();
    }
//    $("parent").onclick=alertP;
//    $("child").onclick=alertC;
//    $("grandson").onclick=alertG;
    $("parent").addEventListener("click",alertP,true);
    $("child").addEventListener("click",alertC,false);
    $("grandson").addEventListener("click",alertG,true);
</script>
</body>
</html>

  

点击最里层的div,弹出的内容顺序是:

Parent,Grandson;

  

IE中则只有事件冒泡的过程,就是只有从子节点向父节点回传的过程,阻断事件传播可以用event.cancelBubble.这里就不在多举测试例子

 

此外,W3C标准的事件模型中e.preventDefault也非常有用,它主要是用来阻止事件的默认行为发生.IE中与它相对应的是window.event.returnValue=false;

 

 


 



posted on 2014-05-25 01:04  Young_Junior_Man  阅读(252)  评论(0)    收藏  举报

导航