捕获型事件模型与冒泡型事件模型的应用场合

Bubble
<!DOCTYPE html>
<html>
<head>
    <style>
        #a {
            width: 500px;
            height: 500px;
            background: #ff0000
        }
        #b {
            width: 200px;
            height: 200px;
            background: #00ff00
        }
    </style>
</head>
<body>
    <div id="a">
        <div id="b"></div>
    </div>
</body>
<script>
    //函数
    var fa = function () {
        alert("a");
    }

    var fb = function (event) {
        alert("b");
        event = event || window.event;
        if(event.stopPropagation)
            event.stopPropagation();
        else
            event.cancelBubble = true;
    }

    //A
    var A = document.getElementById("a");
    A.addEventListener("click", fa, false);
    //B
    var B = document.getElementById("b");
    B.addEventListener("click", fb, false);

</script>
</html>


Catch:

<!DOCTYPE html>
<html>
<head>
    <style>
        #a {
            width: 500px;
            height: 500px;
            background: #ff0000
        }
        #b {
            width: 200px;
            height: 200px;
            background: #00ff00
        }
    </style>
</head>
<body>
    <div id="a">
        <div id="b"></div>
    </div>
</body>
<script>
    //函数
    var fa = function () {
        alert("a");
    }

    var fb = function (event) {
        alert("b");
    }

    //A
    var A = document.getElementById("a");
    A.addEventListener("click", fa, true);
    //B
    var B = document.getElementById("b");
    B.addEventListener("click", fb, true);

</script>
</html>

 

 

捕获型事件模型与冒泡型事件模型的应用场合

标准事件模型为我们提供了两种方案,可能很多朋友分不清这两种不同模型有啥好处,为什么不只采取一种模型。
这里抛开IE浏览器讨论(IE只有一种,没法选择)什么情况下适合哪种事件模型。

1. 捕获型应用场合

捕获型事件传递由最不精确的祖先元素一直到最精确的事件源元素,传递方式与操作系统中的全局快捷键与应用程序快捷键相似。当一个系统组合键发生时,如果注册了系统全局快捷键监听器,该事件就先被操作系统层捕获,全局监听器就先于应用程序快捷键监听器得到通知,也就是全局的先获得控制权,它有权阻止事件的进一步传递。所以捕获型事件模型适用于作全局范围内的监听,这里的全局是相对的全局,相对于某个顶层结点与该结点所有子孙结点形成的集合范围。

例如你想作全局的点击事件监听,相对于document结点与document下所有的子结点,在某个条件下要求所有的子结点点击无效,这种情况下冒泡模型就解决不了了,而捕获型却非常适合,可以在最顶层结点添加捕获型事件监听器,伪码如下:

1.functionglobalClickListener(event) {
2.    if(canEventPass == false) {
3.        //取消事件进一步向子结点传递和冒泡传递
4.        event.stopPropagation();
5.        //取消浏览器事件后的默认执行
6.       event.preventDefault();
7.    }
8.}

这样一来,当canEventPass条件为假时,document下所有的子结点click注册事件都不会被浏览器处理。

2. 冒泡型的应用场合

可以说我们平时用的都是冒泡事件模型,因为IE只支持这模型。这里还是说说,在恰当利用该模型可以提高脚本性能。在元素一些频繁触发的事件中,如onmousemove, onmouseover,onmouseout,如果明确事件处理后没必要进一步传递,那么就可以大胆的取消它。此外,对于子结点事件监听器的处理会对父层监听器处理造成负面影响的,也应该在子结点监听器中禁止事件进一步向上传递以消除影响。

综合案例分析

最后结合下面HTML代码作分析:

 
01.<</code>body onclick="alert('current is body');">
02.  <</code>div id="div0" onclick="alert('current is '+this.id)">
03.      <</code>div id="div1" onclick="alert('current is '+this.id)">
04.         <</code>div id="div2">
05.            <</code>div id="event_source"
06.                  onclick="alert('current is '+this.id)"
07.                  style="height:200px;width:200px;">
08.            </</code>div>
09.         </</code>div>
10.   </</code>div>
11.  </</code>div>
12.</</code>body>

HTML运行后点击红色区域,这是最里层的DIV,根据上面说明,无论是DOM标准还是IE,直接写在html里的监听处理函数是事件冒泡传递时调用的,由最里层一直往上传递,所以会先后出现
current is event_source
current is div2
current is div1
current is div0
current is body

添加以下片段:

 
1.var div2 = document.getElementByIdx_x('div2');
2.addEventHandler(div2,'click',function(event){
3.   event = event || window.event;
4.   if(event.stopPropagation)
5.     event.stopPropagation();
6.   else event.cancelBubble = true;
7.},false);

当点击红色区域后,根据上面说明,在泡冒泡处理期间,事件传递到div2后被停止传递了,所以div2上层的元素收不到通知,所以会先后出现:
current is event_source
current is div2

在支持DOM标准的浏览器中,添加以下代码:

 
1.document.body.addEventListener('click',function(event){
2.     event.stopPropagation();
3.},true);

以上代码中的监听函数由于是捕获型传递时被调用的,所以点击红色区域后,虽然事件源是ID为event_source的元素,但捕获型选传递,从最顶层开始,body结点监听函数先被调用,并且取消了事件进一步向下传递,所以只会出现current is body

 
posted @ 2017-10-16 14:41  sky20080101  阅读(367)  评论(0)    收藏  举报