js事件捕获和冒泡

事件冒泡

微软提出了名为事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。

事件捕获

网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。

W3C模型

上面两种模式都有合理之处,所以W3C模型是将两者进行中和,在W3C模型中,任何事件发生时,先从顶层开始进行事件捕获,直到事件触发到达了事件源元素。然后,再从事件源往上进行事件冒泡,直到到达document。

1
element.addEventListener(event, function, useCapture)

event:事件名称

function:事件触发后的执行函数

useCapture:指定事件是在捕获阶段执行(true)还是在冒泡阶段执行(false,默认)

阻止冒泡

上面我们知道事件是通过传播后才有冒泡和捕获的概念,但是有时候这并不是我们想要的,我们要阻止时间的传播,怎么办呢?

1
event.stopPropagation();

IE下阻止事件传播的方法

1
window.event.returnValue = false;

冒泡和捕获演示

事件代理

假如我们有一个学生列表,我们希望点列表中的任意一个名字,就用alert的方式把学生的名字弹出。当名字少时我们可以给每一个名字添加点击事件,这很明显是一个很笨的做法。我们可以考虑用上面的事件传播的特性来处理,通常我们叫它事件代理的方法。

HTML代码如下:

1
2
3
4
5
6
7
8
<ul id="names">
<li>张三</li>
<li>李四</li>
<li>王五</li>
<li>小明</li>
<li>小黑</li>
<li>小白</li>
</ul>

js绑定事件:

1
2
3
4
5
6
7
8
9
(function(){
var names = document.getElementById("names");
names.addEventListener('click',function(e){
var x = e.target;
if(x.nodeName.toLowerCase() === 'li'){
alert('name='+x.innerHTML)
}
})
})();

我们通过获取到点击的目标元素(e.target),然后再对目标元素做出一系列的操作。

当然实现这一方式的方法还很多,这里就介绍这一种。

事件都未考虑兼容性问题,具体实施的时候可能有差别

参考资料:

不兼容的事件冒泡: http://blog.csdn.net/hdchangchang/article/details/9224579

HTML DOM addEventListener() 方法: http://www.runoob.com/jsref/met-element-addeventlistener.html

JS浏览器兼容性问题: http://dada-fangfang.iteye.com/blog/811749