捕获和js 冒泡 捕获同时存在点击子级,只能触发捕获吗

js之事件冒泡和事件捕获详细介绍
字体:[ ] 类型:转载 时间:
事件——怎样使用事件以及IE和DOM事件模型之间存在哪些主要差别,有需要的朋友可以参考一下
(1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。
& IE 5.5: div -& body -& document
& IE 6.0: div -& body -& html -& document
& Mozilla 1.0: div -& body -& html -& document -& window
(2)捕获型事件(event capturing):事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)。
(3)DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件,但是,捕获型事件先发生。两种事件流会触及DOM中的所有对象,从document对象开始,也在document对象结束。
& DOM事件模型最独特的性质是,文本节点也触发事件(在IE中不会)。
支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,还是事件冒泡时执行。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果。
事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。假设一个元素div,它有一个下级元素p。&div&  &p&元素&/p&&/div&这两个元素都绑定了click事件,如果用户点击了p,它在div和p上都触发了click事件,那这两个事件处理程序哪个先执行呢?事件顺序是什么?&两种模型以前,Netscape和Microsoft是不同的实现方式。
Netscape中,div先触发,这就叫做事件捕获。
Microsoft中,p先触发,这就叫做事件冒泡。
两种事件处理顺序刚好相反。IE只支持事件冒泡,Mozilla, Opera 7 和 Konqueror两种都支持,旧版本的Opera's 和 iCab两种都不支持 。
事件捕获当你使用事件捕获时,父级元素先触发,子级元素后触发,即div先触发,p后触发。
事件冒泡当你使用事件冒泡时,子级元素先触发,父级元素后触发,即p先触发,div后触发。
W3C模型W3C模型是将两者进行中和,在W3C模型中,任何事件发生时,先从顶层开始进行事件捕获,直到事件触发到达了事件源元素。然后,再从事件源往上进行事件冒泡,直到到达document。
程序员可以自己选择绑定事件时采用事件捕获还是事件冒泡,方法就是绑定事件时通过addEventListener函数,它有三个参数,第三个参数若是true,则表示采用事件捕获,若是false,则表示采用事件冒泡。
ele.addEventListener('click',doSomething2,true)
false=冒泡
传统绑定事件方式在一个支持W3C DOM的浏览器中,像这样一般的绑定事件方式,是采用的事件冒泡方式。
ele.onclick = doSomething2
IE浏览器如上面所说,IE只支持事件冒泡,不支持事件捕获,它也不支持addEventListener函数,不会用第三个参数来表示是冒泡还是捕获,它提供了另一个函数attachEvent。
ele.attachEvent("onclick", doSomething2);
附:事件冒泡(的过程):事件从发生的目标(event.srcElement||event.target)开始,沿着文档逐层向上冒泡,到document为止。
事件的传播是可以阻止的:• 在W3c中,使用stopPropagation()方法• 在IE下设置cancelBubble = true;在捕获的过程中stopPropagation();后,后面的冒泡过程也不会发生了~3.阻止事件的默认行为,例如click &a&后的跳转~• 在W3c中,使用preventDefault()方法;• 在IE下设置window.event.returnValue =4.哇,终于写完了,一边测试一边写的额,不是所有的事件都能冒泡,例如:blur、focus、load、unload,(这个是从别人的文章里摘过来的,我没测试)。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具js 中事件冒泡和事件捕获,以及怎么解决_百度知道最近在学习javascript中遇到了一些困难,比如冒泡和捕获,很多次被提到,但又不知究竟应用在何处。找到了一些好文章解惑,在这里分享给大家。
quirksmode的一系列文章都不错,通俗易懂,这篇只是一系列中的某一篇,有机会把javascript这系列都翻译给大家。
原文地址在这里,句子中有标注“(?)”表示我对这个句子不是很理解,可能有误。正式开始:
事件的发生顺序
这个问题的起源非常简单,假设你在一个元素中又嵌套了另一个元素
-----------------------------------
| element1
-------------------------
-------------------------
-----------------------------------
:并且两者都有一个onClick事件处理函数(event handler)。如果用户单击元素2,则元素1和元素2的单击事件都会被触发。但是哪一个事件先被触发?哪一个事件处理函数会被首先执行?换句话说,事件的发生顺序到底如何?
不出所料,在那些“不堪回首”(浏览器大战)的日子里,Netscape和微软有两种截然不同的处理方法:
Netscape主张元素1的事件首先发生,这种事件发生顺序被称为捕获型微软则保持元素2具有优先权,这种事件顺序被称为冒泡型
这两种事件顺序是截然相反的。Explorer浏览器只支持冒泡事件,Mozilla,Opera7和Konqueror两者都支持。而更古老的opera和iCab两者都不支持
捕获型事件
当你使用捕获型事件时
---------------| |-----------------
| element1
-----------| |-----------
-------------------------
Event CAPTURING
-----------------------------------
:元素1的事件处理函数首先被触发,元素2的事件处理函数最后被触发
冒泡型事件
当你使用冒泡型事件时
---------------| |-----------------
| element1
-----------| |-----------
-------------------------
Event BUBBLING
-----------------------------------
:元素2 的处理函数首先被触发,元素1其次
W3c明智的在这场争斗中选择了一个择中的方案。任何发生在中的事件,首是进入捕获阶段,直到达到目标元素,再进入冒泡阶段
-----------------| |--| |-----------------
| element1
-------------| |--| |-----------
--------------------------------
W3C event model
------------------------------------------
为一个web开发者,你可以选择是在捕获阶段还是冒泡阶段绑定事件处理函数,这是通过addEventListener()方法实现的,如果这个函数的最后一个参数是true,则在捕获阶段绑定函数,反之false,在冒泡阶段绑定函数。
&假设你要做
element1.addEventListener('click',doSomething2,true)
element2.addEventListener('click',doSomething,false)
如果用户单击元素2,则接下来会发生:
(事件在这里就像一个观光客,由外至内游览,逐渐接近被触发的主要元素,然后又反向离开)
单击事件首先进入捕获阶段开始(逐渐接近元素2的方向)。查看元素2的祖先元素中是否有在捕获阶段有onclick处理函数的发现元素1有一个,于是doSomething2被执行事件检查到目标自己(元素2),捕获阶段没有发现更多的处理函数了。事件开始进入冒泡阶段,想当然执行doSomething(),这个绑定于元素2冒泡阶段的函数。事件向远离元素2的方向,查看是否有任何祖先元素在冒泡阶段绑定了一个处理函数。没有这样的情况,所以什么也没有发生
相反的情况是:
element1.addEventListener('click',doSomething2,false)
element2.addEventListener('click',doSomething,false)
现在如果用户点击元素2会发生:
单击事件进入捕获阶段。查看元素2的祖先元素中是否有在捕获阶段有onclick处理函数的,结果一无所获事件检查到目标自己。事件开始进入冒泡阶段,并且执行绑定于元素2冒泡阶段的函数。doSomething()事件开始远离目标,检查元素2的祖先元素中是否有在冒泡阶段绑定了处理函数的发现了一个,于是元素1的doSomething2()被执行
兼容性和传统模式
在支持w3c dom(文档对象模型) 的浏览器中,传统的事件绑定方法是
element1.onclick = doSomething2;
默认被视为在绑定于冒泡阶段
使用冒泡型事件
很少的开发人员会有意识的去使用冒泡型事件或者捕获型事件。在他们今天制作的网页中,没有必要让一个事件因为冒泡而被好几个函数处理。但是有时用户通常会很疑惑,因为在他们只点击了一次鼠标之后出现了许多种情况(多个函数被执行,因为冒泡)。而大多数情况下你还是希望你的处理函数相互独立的。当用户点击了某一个元素,发生什么,点击另一个元素,又对应发生些什么,相互独立,而不因为冒泡连锁。
一直在发生
首先你要明白的是事件捕获或者冒泡一直在发生。如果你给整个页面文档的定义一个通用onclick处理函数
document.onclick = doS
if (document.captureEvents) document.captureEvents(Event.CLICK);
//第二句话我也不知道什么意思,初学者,希望有能人能解释
在页面上单击任何元素的单击事件,最终会冒泡至页面最高文档层,因此触发那个通用的处理函数,除非之前一个处理函数明确的指出终止冒泡,这样才冒泡才不会传播到整个文档层面
用法(这一小节翻译的不好,因为没有实战,我也不是很理解,可以在留言中补充,我会更新)
因为任何事件传播终止于页面文档(这个最高层),这使默认的事件处理函数变得可能,假设你有这样一个页面
------------------------------------
| document
---------------
------------
| element1
| element2 |
---------------
------------
------------------------------------
element1.onclick = doS
element2.onclick = doS
document.onclick = defaultF
现在如果用户单击元素1或者元素2,doSomething()将被执行。如果你愿意的话,如果你不想让事件冒泡至执行defaultFunction(),你可以在这里阻止事件冒泡向上传播,。但是如果用户点击页面上的其他部位,defaultFunction()还是会被执行。这样的效果或许有时能用的上。
设置页面-——使处理函数有范围较大的触发面积,在“拖拽效果”脚本中是必须的。一般来说在某一个元素层上发生 mousedown事件意味着选择了这个元素,并且使它能够响应mousemove事件。虽然mousedown通常绑定于这个元素层上以避免浏览器bug,但是其他两者的事件函数的范围必须是整个页面(?)
记住浏览器学的第一法则(First Law of Browserology)是:一切皆有可能(anything can happen),并且是在你起码有点准备的时候。所以有可能发生的是,用户拖拽时,大幅度在页面上移动他的鼠标,脚本却不能在大幅度中做出反应,以至于鼠标也就不再停留在元素层上了
如果onmouseover处理函数绑定在元素层上,这个元素层不会再对鼠标的移动有任何反应,这会让用户觉得奇怪如果onmouseup处理函数绑定在元素层上,事件也不能被触发,后果是,用户想放下这个元素层后,元素层持续对鼠标移动做出反应。这会引起(用户)更多的迷惑(?)
所以在这个例子中,事件冒泡非常的有用,因为将你的处理函数放在页面层能保证他们一直能被执行
把它给关了
但是一般情况下,你会想关了所有的冒泡和捕获以保证函数之间不会打扰到对方。除此之外,如果你的文档结构相当的复杂(许多table之间相互嵌套或者诸如此类),你也会为了节省系统资源,而关闭冒泡。此时浏览器不得不检查目标元素的每一个祖先,看是否它有一个处理函数。即使一个都没有找到,刚刚的搜索同样花费不少时间
在微软的模型中,你必须设置事件的cancelBubble的属性为true
window.event.cancelBubble = true
在w3c模型中你必须调用事件的stopPropagation()方法
e.stopPropagation()
这会阻止所有冒泡向外传播。而作为跨浏览器解决方案应该这么作:
function doSomething(e)
if (!e) var e = window.
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
在支持cancelBubble属性的浏览器中设置cancelBubble无伤大雅。浏览器会耸一耸肩然后创造一个这个属性。当然这也并不能真正的取消冒泡,但至少能保证这条命令是安全正确的
currentTarget
像我们之前看到的一样,一个事件用target或者是srcElement属性用来表示事件究竟发生在哪个目标元素上(即用户最初点击的元素)。在我们的例子中是元素2,因为我们单击了它。
非常重要的是,要明白在捕获或者冒泡阶段的目标元素是不变的,它始终与元素2相关联。
但是假设我们绑定了以下函数
element1.onclick = doS
element2.onclick = doS
如果用户单击元素2, doSomething()会被执行两次。但是你怎么知道哪个html元素正在响应这个事件?target/srcElement也没有给出线索,但人们总是更倾向于元素2,因为它是引起事件的原因(因为用户点击的是它)。
为了解决这个问题,w3c 增加了currentTarget这个属性,它就指向正在处理事件的元素:这恰是我们需要的。很不幸的是微软模型中并没有相似的属性
你也可以使用”this”关键字。在上面的例子中,它相当于正在处理事件的html元素,就像currentTarget。
微软模型的问题
但是当你使用微软事件绑定模型时,this关键字并不相当于HTML元素。联想缺少类似currentTarget属性的微软模型(?)——按上面的代码操作的话,你这么做便意味着:
element1.attachEvent('onclick',doSomething)
element2.attachEvent('onclick',doSomething)
你无法确切知道哪一个HTML元素正在负责处理事件,这是微软事件绑定模型最严重的问题,对我来说,这也是我从不使用它的原因,哪怕是在开发仅供Windows下的IE的应用程序
我希望能够尽快增加currentTarget类似的属性——或者遵循标准?web开发者们需要这些信息
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:7418次
排名:千里之外
原创:17篇
转载:53篇
(5)(8)(3)(2)(2)(2)(8)(11)(7)(5)(2)(9)(7)W3C下的冒泡和捕获机制。到底是冒泡呢。还是捕获呢。一个DOM元素绑定多个事件时如何执行。 - 推酷
W3C下的冒泡和捕获机制。到底是冒泡呢。还是捕获呢。一个DOM元素绑定多个事件时如何执行。
在准备阿里前端面试的时候看到这么一道题。
一个DOM元素绑定两个事件,一个冒泡,一个捕获,则事件会执行多少次,执行顺序如何。
这导致了我对冒泡和捕获又进一步深入的了解。(永远都在发现自己知识匮乏的日子中度过人生真是好抓急啊。)
首先冒泡和捕获是怎么一回事。
简单点说。冒泡就是从下往上,像鱼吐泡,泡泡是从下往上升的,也就是DOM元素被触法事件时(此时的dom元素为目标元素),目标元素事件执行后,它的祖先元素所绑定的事件会向上顺序执行。
如下代码,有四个div嵌套元素,均绑定了click事件,addEventListener函数的第三个参数设置为false说明不为捕获事件,即为冒泡事件。该代码执行结果如下:
点击one元素,输出one;
点击two元素,输出
点击three元素,输出 three two one;
点击four元素,输出 four three two one;
&div id='one'&
&div id='two'&
&div id='three'&
&div id='four'&
&script type='text/javascript'&
var one=document.getElementById('one');
var two=document.getElementById('two');
var three=document.getElementById('three');
var four=document.getElementById('four');
one.addEventListener('click',function(){
alert('one');
two.addEventListener('click',function(){
alert('two');
three.addEventListener('click',function(){
alert('three');
four.addEventListener('click',function(){
alert('four');
而捕获则相反。当触发目标元素时,会从目标元素的最顶层的祖先元素事件往下执行到目标元素为止。
将上面的代码第三个参数均改为true,则执行结果如下:
点击one,输出one;
点击two,输出one two;
点击three,输出one two three;
点击four,输出one two three four;
很明显执行顺序是不同的。
以上便是冒泡和捕获的基本理解。
而在一篇原创翻译中了解到W3C的执行顺序是择中的。即
任何发生在
中的事件,首是进入捕获阶段,直到达到目标元素,再进入冒泡阶段。
(原文链接:/hh54188/archive//2343357.html。)
不过就是这篇文中的例子只有两个dom元素。测试时无法充分理解。我自己便增加了两个元素来理解。
首先,无论是冒泡事件还是捕获事件,元素都会先执行捕获阶段
仍然以上面的代码为例子,假设目标元素为four,也就是four被点击,执行结果是一样,那么它的执行过程呢?
其实过程就是,从four元素的最顶层的祖先开始向下判断是否有捕获事件的元素,即第三个参数为true的绑定事件的元素。
从上往下,如有捕获事件,则执行;一直向下到目标元素后,从目标元素开始向上执行冒泡元素,即第三个参数为false的绑定事件的元素。(在向上执行过程中,已经执行过的捕获事件不再执行,只执行冒泡事件。)
如下代码:
此时点击four元素,four元素为目标元素,one为根元素祖先,从one开始向下判断执行。
one为捕获事件,输出one;
two为冒泡事件,忽略;
three为捕获时间,输出three;
four为目标元素,开始向上冒泡执行,输出four;(从此处分为两部分理解较容易。)
three为捕获已执行,忽略;
two为冒泡事件,输出two;
one为捕获已执行,忽略。
最终执行结果为:one three four two
(在这里可能会有疑问,目标元素是什么事件有区别吗?我的测试结果是没有区别的,无论目标元素是捕获还是冒泡,在w3c下都是先从根元素执行捕获到目标元素,再从目标元素向上执行。)
有疑问的话可以在这个例子上将其他三个元素作为目标元素测试。
例如,three作为目标元素,执行结果为:one three two(因为two是冒泡事件,在向下执行时没有执行到。)
one.addEventListener('click',function(){
alert('one');
two.addEventListener('click',function(){
alert('two');
three.addEventListener('click',function(){
alert('three');
four.addEventListener('click',function(){
alert('four');
最后就是讨论一个DOM元素绑定多个事件的执行过程。
执行次数:绑定了几个事件便执行几次。
如下代码,two元素绑定了两个不同事件,点击two都会执行这两个事件。而执行顺序有所差异
1、如果two为目标元素,目标元素的事情按顺序执行,而其他元素根据W3C的标准执行,即先捕获后冒泡。
点击two执行结果:one(因为是two的父元素支持捕获事件所以先执行) &two,bubble &two,capture(顺序执行,注意逗号不是间隔,是输出内容。)
2、如果目标元素不是two,则two的两个事件按先捕获后冒泡触发执行,也就是跟前面讨论的执行过程是一样的,只不过两个事件都绑定在同一个DOM元素上。
点击three执行结果:one two,capture three,bubble two,bubble
one.addEventListener('click',function(){
alert('one');
two.addEventListener('click',function(){
alert('two,bubble');
two.addEventListener('click',function(){
alert('two,capture');
three.addEventListener('click',function(){
alert('three,bubble');
four.addEventListener('click',function(){
alert('four');
以上便是我自己的理解了。不知道各位博友能否看得明白。欢迎评论交流。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致转载请注明出处:
● 事件分为三个阶段: & 事件捕获 --& &事件目标 --& &事件冒泡
●&事件捕获:事件发生时(onclick,onmouseover&&)首先发生在document上,然后依次传递给body、&&最后到达目的节点(即事件目标)。
●&事件冒泡:事件到达事件目标之后不会结束,会逐层向上冒泡,直至document对象,跟事件捕获相反
1、onlick --&事件冒泡,重写onlick会覆盖之前属性,没有兼容性问题
ele.onclik = null;
//解绑单击事件,将onlick属性设为null即可
2、addEventListener(event.type, handle, boolean); IE8及以下不支持,属于DOM2级的方法,可添加多个方法不被覆盖
//事件类型没有on,false 表示在事件第三阶段(冒泡)触发,true表示在事件第一阶段(捕获)触发。 如果handle是同一个方法,只执行一次。
ele.addEventListener('click', function(){ }, false);
//解绑事件,参数和绑定一样
ele.removeEventListener(event.type, handle, boolean);
3、attachEvent(event.type, handle ); IE特有,兼容IE8及以下,可添加多个事件处理程序,只支持冒泡阶段
//如果handle是同一个方法,绑定几次执行几次,这点和addEventListener不同,事件类型要加on,例如onclick而不是click
ele.attachEvent('onclick', function(){ });
//解绑事件,参数和绑定一样
ele.detachEvent("onclick", function(){ });
4、默认事件行为:href=""链接,submit表单提交等
  ●&阻止默认事件:
(1)&阻止独享属性(通过on这种方式)绑定的事件的默认事件
ele.onclick = function() {
//你的代码
return false;
//通过返回false值阻止默认事件行为
(2)event.preventDefault( );&阻止通过&addEventListener( )&添加的事件的默认事件
element.addEventListener("click", function(e){
var event = e || window.
event.preventDefault( );
//阻止默认事件
(3)event.returnValue =&阻止通过&attachEvent( )&添加的事件的默认事件
element.attachEvent("onclick", function(e){
var event = e || window.
event.returnValue = false;
//阻止默认事件
5、接下来我们把事件绑定以及事件解绑封装成为一个函数,兼容浏览器,包括IE6及以上
// 事件绑定
function addEvent(element, eType, handle, bol) {
if(element.addEventListener){
//如果支持addEventListener
element.addEventListener(eType, handle, bol);
}else if(element.attachEvent){
//如果支持attachEvent
element.attachEvent("on"+eType, handle);
//否则使用兼容的onclick绑定
element["on"+eType] =
// 事件解绑
function removeEvent(element, eType, handle, bol) {
if(element.addEventListener){
element.removeEventListener(eType, handle, bol);
}else if(element.attachEvent){
element.detachEvent("on"+eType, handle);
element["on"+eType] = null;
& & & & & & & & & & & & & &-----------------------------------------------------------------------------------------------------------------------------------------------
A.●&事件冒泡、事件捕获阻止:
event.stopPropagation( );& & & & & & & & // 阻止事件的进一步传播,包括(冒泡,捕获),无参数
event.cancelBubble =&& & & & & & // true 为阻止冒泡
B.●&事件委托:利用事件冒泡的特性,将里层的事件委托给外层事件,根据event对象的属性进行事件委托,改善性能。
使用事件委托能够避免对特定的每个节点添加事件监听器;事件监听器是被添加到它们的父元素上。事件监听器会分析从子元素冒泡上来的事件,找到是哪个子元素的事件。
来个例子吧,如果要单独点击table里面的td,普通做法是for循环给每个td绑定事件,td少的话性能什么差别,td如果多了,就不行了,我们使用事件委托:
&!-- HTML --&
&table id="out" border="1" style="cursor:"&
  &td&table01&/td&
  &td&table02&/td&
  &td&table03&/td&
  &td&table04&/td&
  &td&table05&/td&
  &td&table06&/td&
  &td&table07&/td&
  &td&table08&/td&
  &td&table09&/td&
  &td&table10&/td&
var out = document.getElementById("out");
if(out.addEventListener){
out.addEventListener("click",function(e){
var e = e||window.
//IE没有e.target,有e.srcElement
var target = e.target||e.srcE
//判断事件目标是否是td,是的话target即为目标节点td
if(target.tagName.toLowerCase()=="td"){
changeStyle(target);
console.log(target.innerHTML);
out.attachEvent("onclick",function(e){
var e = e||window.
//IE没有e.target,有e.srcElement
var target = e.target||e.srcE
//判断事件目标是否是td,是的话target即为目标节点td
if(target.tagName.toLowerCase()=="td"){
changeStyle(target);
console.log(target.innerHTML);
26 function changeStyle(ele){
ele.innerHTML = "已点击"
ele.style.background="#900";
ele.style.color = "#fff"; }
关于事件就到这里了。。。
张小窝 -- web前端开发路上 & &原创。
阅读(...) 评论()}

我要回帖

更多关于 js 冒泡 捕获 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信