关于事件流,事件冒泡和事件捕获

 

1.事件流

假设有这样一个场景:

有一个导航条:div > ul > li > a,每个元素块宽高一样,就像是一组同心圆。如果我们点击a元素,那么浏览器会认为单击事件不仅仅发生在a上。换句话说,在我们单击a元素的同事,我们也单击了容器中的其他元素。

事件流描述的是从页面中接收事件的顺序。但有意思的是,IE 和 Netscape 却分别提出了不一样的事件流概念。IE 的事件流是事件冒泡流,而Netscape的事件流是事件捕获流

 

那么问题来了,什么是事件冒泡?什么是事件捕获?

2.事件冒泡

事件冒泡:就是说事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点。

<!DOCTYPE html>
<html>
<head>
         <title>example</title>
</head>
<body>
         <div>click</div>     
</body> 
<html>   

以上代码,如果我们点击页面中的<div>,那么这个click事件会按照以下顺序传播:

<div>   =>   <body>   =>   <html>   =>   document

3.事件捕获

事件捕获:与事件冒泡差不多完全相反,事件捕获思想是从不太具体的节点应该更早接收到事件,而具体的节点应该是最后接收到事件。

那么如果我们点击页面中的<div>,那么这个click事件会按照以下顺序传播:

 document   =>   <html>   =>   <body>   =>   <div>

虽然事件捕获是Netscap唯一支持的事件流模型,但是IE9/safari/chrome/opera/firefox目前都支持这种事件流模型。尽管“DOM2级事件”规范要求事件应该从document对象开始传播,但是这些浏览器都是从window对象开始捕获事件的。

 

那么问题又来了,什么是“DOM2级事件”?

4.DOM事件流

“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段--处于目标阶段--事件冒泡阶段。

还是用上面的代码为例:

document   =>   <html>   =>   <body>   =>   <div>   =>   <body>   =>   <html>   =>   document

                   捕获阶段                                处于目标阶段                    冒泡阶段

在DOM事件流中,实际目标在捕获阶段是不会接收到事件的。这意味着捕获阶段到<body>就停止了。下一个阶段是“处于目标阶段”,即事件在<div>上发生,而这一个阶段被堪称冒泡阶段的一部分。继而冒泡阶段发生,事件传回document。

 

 “DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener( )和removeEventListener( )。所有的DOM节点中都包含这两个方法,并且它们接收3个参数:要处理的事件,作为事件处理程序的函数和一个布尔值。布尔值如果是true,表示在捕获阶段调用事件处理程序,如果是false,表示在冒泡阶段调用事件处理程序。

var btn = document.getElementIdBy("mybtn");
btn.addEventListener("click",function(){
     aliert(this.id);
},false);
btn.removeListener("click",function(){
    aliert(this.id);
},false);

注意:以上代码中的函数为匿名函数,将无法移除匿名函数,因为这完全是两个不同的函数。

var btn = document.getElementIdBy("mybtn");
var handler = function(){
     aliert(this.id);
}
btn.addEventListener("click",handler,false);
btn.removeListener("click",handler,false);

这样就没问题了。

另外,应该尽可能把事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。

 

posted @ 2017-09-13 16:24  Cooper_Yao  阅读(1343)  评论(0编辑  收藏  举报