本文详细解析JavaScript中事件冒泡与事件捕获两种事件流模型的历史背景与执行顺序,阐述addEventListener第三个参数的作用。通过对比传统绑定方式与事件代理技术,说明如何利用事件冒泡特性优化性能并简化代码维护,同时提供IE低版本浏览器的兼容方案。
事件冒泡与捕获机制概述
事件冒泡和事件捕获机制分别由微软和网景公司提出,旨在解决网页中事件流的触发顺序问题。
<div id="outer">
<p id="inner">Click me!</p>
</div>
在一个包含子元素p的div元素中,若两者均绑定了click事件处理函数,确定哪个函数先被触发是关键问题。
为解决上述触发顺序的不确定性,微软与网景提出了两种截然相反的事件处理概念。
事件冒泡模型详解
事件冒泡
微软提出的事件冒泡(event bubbling)模型,形象地比喻为石子投入水中,气泡从水底向水面升起的過程。具体而言,事件从最内层元素开始触发,逐层向上传播,直至到达document对象。
基于事件冒泡模型,前述示例中click事件的触发顺序为:p -> div -> body -> html -> document。
事件捕获模型详解
事件捕获
网景公司提出的事件捕获(event capturing)模型与冒泡相反,事件从最外层元素开始触发,逐渐向下传播至最具体的目标元素。
在事件捕获模型下,前述示例中click事件的触发顺序为:document -> html -> body -> div -> p。
addEventListener参数配置
addEventListener的第三个参数
“DOM2级事件”规范规定的事件流同时包含捕获阶段和冒泡阶段,开发者可通过配置选择事件处理函数在哪个阶段执行。
addEventListener是JavaScript中用于为特定元素绑定事件处理函数的常用方法,它接收三个参数。
element.addEventListener(event, function, useCapture) 第一个参数指定要绑定的事件类型,第二个参数为事件触发后执行的回调函数。第三个参数useCapture默认为false,表示在冒泡阶段调用处理函数;若设为true,则在捕获阶段调用。
事件代理技术应用
事件代理
在实际开发中,利用事件流的特性,可以采用事件代理(Event Delegation)技术来优化代码。
<ul id="color-list">
<li>red</li>
<li>yellow</li>
<li>blue</li>
<li>green</li>
<li>black</li>
<li>white</li>
</ul>
若需点击页面中的li元素并输出其颜色,传统做法如下。
代码如下:
(function(){
var color_list = document.getElementById('color-list');
var colors = color_list.getElementsByTagName('li');
for(var i=0;i<colors.length;i++){
colors[i].addEventListener('click',showColor,false);
};
function showColor(e){
var x = e.target;
alert("The color is " + x.innerHTML);
};
})();
利用事件流的特性,仅需绑定一个事件处理函数即可实现相同功能。
代码如下:
(function(){
var color_list = document.getElementById('color-list');
color_list.addEventListener('click',showColor,false);
function showColor(e){
var x = e.target;
if(x.nodeName.toLowerCase() === 'li'){
alert('The color is ' + x.innerHTML);
}
}
})();
事件代理的优势不仅在于将多个事件处理函数合并为一个,还允许对不同元素应用不同的处理逻辑。若列表中添加其他元素(如a、span等),无需重新循环绑定,只需修改代理函数的逻辑即可。
冒泡与捕获的选择建议
冒泡还是捕获?
对于事件代理而言,在捕获或冒泡阶段处理并无显著优劣差异。鉴于事件冒泡模型被所有主流浏览器兼容,从兼容性角度建议优先使用冒泡模型。
IE浏览器兼容性处理
IE浏览器兼容
IE浏览器对addEventListener的支持有限,仅IE9及以上版本可用。

为兼容旧版IE浏览器,可使用IE特有的attachEvent函数。
object.setCapture(); object.attachEvent(event, function) 这两个参数与addEventListener类似,分别对应事件和处理函数,默认在冒泡阶段调用。需注意,事件名需加上“on”前缀(如“onload”、“onclick”等)。
以上即为本文的全部内容,希望读者有所收获。