原文:https://segmentfault.com/a/1190000000749838

事件冒泡与事件捕获

事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题。

<div id="outer">
<p id="inner">Click me!</p>
</div>

上面的代码当中一个div元素当中有一个p子元素,如果两个元素都有一个click的处理函数,那么我们怎么才能知道哪一个函数会首先被触发呢?

为了解决这个问题微软和网景提出了两种几乎完全相反的概念。

事件冒泡

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

因此上面的例子在事件冒泡的概念下发生click事件的顺序应该是p -> div -> body -> html -> document

事件捕获

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

上面的例子在事件捕获的概念下发生click事件的顺序应该是document -> html -> body -> div -> p

addEventListener的第三个参数

“DOM2级事件”中规定的事件流同时支持了事件捕获阶段和事件冒泡阶段,而作为开发者,我们可以选择事件处理函数在哪一个阶段被调用。

addEventListener方法用来为一个特定的元素绑定一个事件处理函数,是JavaScript中的常用方法。addEventListener有三个参数:

element.addEventListener(event, function, useCapture)

第一个参数是需要绑定的事件,第二个参数是触发事件后要执行的函数。而第三个参数默认值是false,表示在事件冒泡的阶段调用事件处理函数,如果参数为true,则表示在事件捕获阶段调用处理函数。请看例子

事件代理

在实际的开发当中,利用事件流的特性,我们可以使用一种叫做事件代理的方法。

<ul id="color-list">
<li>red</li>
<li>yellow</li>
<li>blue</li>
<li>green</li>
<li>black</li>
<li>white</li>
</ul>

如果点击页面中的li元素,然后输出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浏览器对addEventListener兼容性并不算太好,只有IE9以上可以使用。

要兼容旧版本的IE浏览器,可以使用IE的attachEvent函数

object.attachEvent(event, function)

两个参数与addEventListener相似,分别是事件和处理函数,默认是事件冒泡阶段调用处理函数,要注意的是,写事件名时候要加上"on"前缀("onload"、"onclick"等)。

【转载】浅谈事件冒泡与事件捕获 - javascript 事件代理的更多相关文章

  1. 关于js事件冒泡和时间捕获

    (1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发. IE 5.5: div -> body -> document IE 6.0: div ...

  2. window.open('') 火狐,IE事件冒泡处理,点击事件冒泡处理

    window.open('') 火狐,IE事件冒泡处理,点击事件冒泡处理 写PC下拉菜单的时候,hover样式显示下拉菜单,可能会这样写 <li class="xb_li1" ...

  3. 浅谈js冒泡事件2

    js冒泡阻止 1. 事件目标 现在,事件处理程序中的变量event保存着事件对象.而event.target属性保存着发生事件的目标元素.这个属性是DOM API中规定的,但是没有被所有浏览器实现 . ...

  4. 浅谈js冒泡事件1

    什么是JS事件冒泡?: 在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这 ...

  5. JS中的事件冒泡(Bubble)和事件捕获(capture)以及如何阻止事件的冒泡

    对“捕获”和“冒泡”这两个概念,通常我们对冒泡了解和使用的会更多一些,因为在我们使用的所有浏览器中,都支持事件冒泡 ,即事件由子元素向祖先元素传播的,就 像气泡从水底向水面上浮一样.而在像firefo ...

  6. 转载-浅谈Ddos攻击攻击与防御

    EMail: jianxin#80sec.comSite: http://www.80sec.comDate: 2011-2-10From: http://www.80sec.com/ [ 目录 ]一 ...

  7. JS事件冒泡机制和兼容性添加事件

    本篇文章主要来讲讲 事件的冒泡机制 和 添加事件的几种方法. 一. JS的时间传递顺序: 捕获阶段 -> 目标阶段 -> 冒泡阶段 捕获阶段是指从父层往子层找.比如 <body> ...

  8. js /jquery停止事件冒泡和阻止浏览器默认事件

    1>js阻止冒泡事件 var el = window.document.getElementById("a"); el.onclick = function (e) { // ...

  9. 关于JS 事件冒泡和onclick,click,on()事件触发顺序

    今天在给JQgrid中的标签添加click事件的时候,发现一个问题. JQgrid的table中,点击任何位置,都会勾选点击行的checkbox,而我希望在点击我的标签的时候,不要勾选checkbox ...

随机推荐

  1. Anaconda 虚拟环境的使用

    目录 前言 1. 创建虚拟环境 2. 虚拟环境管理 3. Conda虚拟环境的包管理 前言 今天把anaconda进行了滚动更新,实体环境python版本也相应从3.6跟新到了3.7.但是问题来了,之 ...

  2. 浅谈solr

    Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口.用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引:也可以通过Http Get操 ...

  3. HTML文本结构及常用标签

    一.什么是HTML? HTML:超文本标签语言 (Hyper Text Markup Language) www万维网的描述性语言. XHTML指可扩展超文本标记语言(标识语言)(EXtensible ...

  4. python 词云小demo

    词云小demo jiebawordcloud 一 什么是词云? 由词汇组成类似云的彩色图形.“词云”就是对网络文本中出现频率较高的“关键词”予以视觉上的突出,形成“关键词云层”或“关键词渲染”,从而过 ...

  5. TensorFlow下利用MNIST训练模型并识别自己手写的数字

    最近一直在学习李宏毅老师的机器学习视频教程,学到和神经网络那一块知识的时候,我觉得单纯的学习理论知识过于枯燥,就想着自己动手实现一些简单的Demo,毕竟实践是检验真理的唯一标准!!!但是网上很多的与t ...

  6. linux 学习笔记 APACHE安装总结

    #cd /usr/local #mkdir APACHE #tar zxvf /usr/etc/DEV/httpd-2.2.9.tar.gz #mv httpd-2.2.9/* . #rm -rf h ...

  7. Codeforces.954I.Yet Another String Matching Problem(FFT)

    题目链接 \(Description\) 对于两个串\(a,b\),每次你可以选择一种字符,将它在两个串中全部变为另一种字符. 定义\(dis(a,b)\)为使得\(a,b\)相等所需的最小修改次数. ...

  8. ES6快速入门(二)数据结构

    ES6快速入门 一.解构 1. 对象解构 let person = { name: 'Tang', age: 28 }; //必须同名,必须初始化 let {name, age} = person; ...

  9. lnmp更改网站文件和MySQL数据库的存放目录

    购买阿里云服务器,一般建议买一个数据盘,也就是系统盘和数据盘分开,将网站文件和Mysql数据库等都保存在数据盘,即使系统盘或者环境出问题,重置系统盘和重新配置环境,都不会影响数据盘的东西. 配置好LN ...

  10. mac中安装 RabbitMQ

    1.brew install rabbitmq 2.安装后,进入/usr/local/Cellar/rabbitmq/3.7.7 ,输入:sbin/rabbitmq-server 出现下面日志,说明启 ...