JavaScript中捕获/阻止捕获、冒泡/阻止冒泡

  事件流描述的是从页面中接收事件的顺序。提出事件流概念的正是IE和Netscape,但是前者提出的是我们常用的事件冒泡流,而后者提出的是事件捕获流。

第一部分:事件冒泡

  即事件开始由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档)。

  下面举一个简单的例子:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>bubble</title>
<style>
button{
background: red;
color:white;
}
#third{
width: 50px;
height: 50px;
border:thin solid red;
}
#second{
width: 100px;
height: 100px;
border:thin solid red;
}
#first{
width:200px;
height: 200px;
border:thin solid red;
}
</style>
</head>
<body>
<div id="first">
<div id="second" >
<div id="third" >
<button id="button">事件冒泡</button>
</div>
</div>
</div>
<script> document.getElementById("button").addEventListener("click",function(){
alert("button");
},false); document.getElementById("third").addEventListener("click",function(){
alert("third");
},false); document.getElementById("second").addEventListener("click",function(){
alert("second");
},false); document.getElementById("first").addEventListener("click",function(){
alert("first");
},false); </script>
</body>
</html>

这时,我们只点击button元素,效果如下:

可以看到,虽然我们只点击了button元素,但是,button外的third、second、first上的事件由内向外以此被触发,触发的顺序是由DOM树的下层到DOM树的最上面,故称为冒泡

说明:尽管这里我使用了DOM2级事件处理程序,并设置每个事件为冒泡阶段发生,但是即使使用DOM0级,得到的结果也是这样的,冒泡是默认的

但是如果我们不希望事件冒泡呢?那么如何阻止事件冒泡

实际上,事件的对象有一个stopPropagation()方法可以阻止事件冒泡,我们只需要把上个例子中button的事件处理程序修改如下:

        document.getElementById("button").addEventListener("click",function(event){
alert("button");
event.stopPropagation();
},false);

这样,点击button后,只会弹出一个弹窗,显示button。

注意:现代所有的浏览器都支持事件冒泡,只是在实现上有一些差别。

说明:

  即该方法不仅仅可以阻止冒泡,还可以阻止捕获和处于目标阶段。

那么冒泡的终点是哪里呢?

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>memory leak</title>
</head>
<body>
<div id="first">
<div id="second">
<button id="button">冒泡</button>
</div>
</div>
<script>
var button = document.getElementById('button'),
second = document.getElementById('second'),
first = document.getElementById('first'),
body = document.body,
html = document.documentElement;
button.addEventListener('click', function () {
alert('button');
});
second.addEventListener('click', function () {
alert('second');
});
first.addEventListener('click', function () {
alert('first');
});
body.addEventListener('click', function () {
alert('body');
});
html.addEventListener('click', function () {
alert('html');
});
window.addEventListener('click', function () {
alert('window');
});
</script>
</body>
</html>

从上面的这段代码可以看出,可以从 button -> div1 -> div2 -> body -> html -> window即最终可以冒泡到window上,即使是有iframe的话,也是不影响的,比如,我们把这个页面嵌入到另外一个页面中, 最终也是会冒泡到这个页面的window,即使是在iframe上添加一个click事件,也是不会冒泡到这个iframe上的,即事件的冒泡是相互独立的。

第二部分:事件捕获

  事件捕获和事件冒泡是刚好相反的,事件捕获是指不太具体的节点应该更早的接收到事件,而最具体的节点应该最后接收到事件。举例如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>bubble</title>
<style>
button{
background: red;
color:white;
}
#third{
width: 50px;
height: 50px;
border:thin solid red;
}
#second{
width: 100px;
height: 100px;
border:thin solid red;
}
#first{
width:200px;
height: 200px;
border:thin solid red;
}
</style>
</head>
<body>
<div id="first">
<div id="second" >
<div id="third" >
<button id="button">事件冒泡</button>
</div>
</div>
</div>
<script> document.getElementById("button").addEventListener("click",function(){
alert("button");
},true); document.getElementById("third").addEventListener("click",function(){
alert("third");
},true); document.getElementById("second").addEventListener("click",function(){
alert("second");
},true); document.getElementById("first").addEventListener("click",function(){
alert("first");
},true); </script>
</body>
</html>

大家可以看到这个例子我只是把addEventListener()方法的第三个参数由前面例子的false修改为了true,也就是使用捕获方式获得button,那么结果如下:

我们可以看到最外层的事件先被触发,最后才是我们点击的button事件被触发,这便是事件捕获。

那么我们如何才能阻止事件的捕获呢?使用event.stopPropagation()方法吗?答案是否定的,这里要知道,stopPropagation()方法只能阻止事件的冒泡,而不能阻止事件捕获。

补充: stopPropagation()方法既可以阻止事件冒泡,也可以阻止事件捕获,也可以阻止处于目标阶段。

但是我们可以使用DOM3级新增事件stopImmediatePropagation()方法来阻止事件捕获,另外此方法还可以阻止事件冒泡。应用如下:

        document.getElementById("second").addEventListener("click",function(){
alert("second");
event.stopImmediatePropagation();
},true);

  这样,就可以在id为second处阻止事件的捕获了。

那么 stopImmediatePropagation() 和 stopPropagation()的区别在哪儿呢?

  后者只会阻止冒泡或者是捕获。 但是前者除此之外还会阻止该元素的其他事件发生,但是后者就不会阻止其他事件的发生。 例子点击这里。

注意:尽管这是Netscape Navigator提出的事件流,但是现在所有的浏览器都支持这种事件流模型。但是由于老的浏览器不支持,所以很少有人使用事件捕获。

第三部分:DOM事件流

  DOM2级事件规定的时间流包括 三个阶段:

  • 事件捕获阶段
  • 处于目标阶段
  • 事件冒泡阶段

  注意:在DOM事件流中,实际的目标在捕获阶段不会接收到事件,下一个阶段是处于目标阶段,这时事件被触发,最后进入事件冒泡阶段。我们认为处于目标阶段是事件冒泡阶段的一部分。

JavaScript中捕获/阻止捕获、冒泡/阻止冒泡的更多相关文章

  1. javascript中的事件冒泡、事件捕获和事件执行顺序

    谈起JavaScript的 事件,事件冒泡.事件捕获.阻止默认事件这三个话题,无论是面试还是在平时的工作中,都很难避免. DOM事件标准定义了两种事件流,这两种事件流有着显著的不同并且可能对你的应用有 ...

  2. 理解JavaScript中的事件处理 阻止冒泡event.stopPropagation();

    原文地址:http://www.cnblogs.com/binyong/articles/1750263.html 这篇文章对于了解Javascript的事件处理机制非常好,将它全文转载于此,以备不时 ...

  3. 在javascript中的浏览器兼容问题以及兼容浏览器汇总(默认事件,阻止冒泡,事件监听。。。)以及解决方式详解

    在javascript中常见的浏览器兼容问题,以及解决方式. 在前端工作当中我们遵循这样的原则:渐进增强和优雅降级   渐进增强(progressive enhancement): 针对低版本浏览器进 ...

  4. [JS]笔记12之事件机制--事件冒泡和捕获--事件监听--阻止事件传播

    -->事件冒泡和捕获-->事件监听-->阻止事件传播 一.事件冒泡和捕获 1.概念:当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,点击子元素时,父元素的oncl ...

  5. JavaScript 进阶教程一 JavaScript 中的事件流 - 事件冒泡和事件捕获

    先看下面的示例代码: <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Jav ...

  6. Javascript中的事件冒泡与捕获

    事件冒泡和事件捕获 起因:今天在封装一个bind函数的时候,发现el.addEventListener函数支持第三个参数,useCapture:是否使用事件捕获,觉得有点模糊 Js事件流 页面的哪一部 ...

  7. 【jQuery】jQuery中的事件捕获与事件冒泡

    在介绍之前,先说一下JavaScript中的事件流概念.事件流描述的是从页面中接受事件的顺序.   一.事件冒泡( Event Bubbling)            IE 的事件流叫做事件冒泡,即 ...

  8. js中关于事件捕获与事件冒泡的小实验

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

  9. JavaScript中的事件冒泡?事件传播的解释

    注:本文来源  可译网 事件冒泡是你在学习javaScript旅途中遇到的一个术语,它涉及到当一个元素被另一个元素嵌套时调用事件处理的顺序,并且两个元素注册了同一个事件(例如,点击事件). 但是事件冒 ...

随机推荐

  1. Markdown会干掉Html吗?

    Markdown会干掉Html吗? 很明显,MarkDown正在已一种比病毒还快的速度传播着,量子的机器人语言也是深受其启发,当然了,在这个东西没搞出来之前,MarkDown就能干很多事情,比如在线编 ...

  2. Centos下编译JDK

    因为OpenJDK是开源的,这里使用openJDK进行编译联系 环境要求 Centos6.7 64位 openjdk-7u40-fcs-src-b43-26_aug_2013.zip bootstra ...

  3. 东大OJ-1051-旅行家的预算

    1051: 旅行家的预算 时间限制: 1 Sec  内存限制: 128 MB 提交: 27  解决: 7 [提交][状态][讨论版] 题目描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市( ...

  4. Linux 配置只安装 64 位软件包

    Centos.RHEL等系统,yum 安装的时候有时候会安装32的,然而我们只需要安装64位的软件! 解决方法: yum只安装 64 位的包,只需在 /etc/yum.conf 中加入 "e ...

  5. 60-chmod 修改文件的权限

    修改文件的权限 chmod [options] who operator permission file-list (符号模式) chmod [options] mode file-list (绝对模 ...

  6. jq 修改input 标签的值

    <input type="number" id="output" placeholder="0" /> jq使用方法 $('#o ...

  7. LAMP安装各种问题解决方案

    LAMP环境配置安装注意安装步骤及说明事项. LAMP安装各种问题解决 1. 访问ftp报错 解决: 关闭selinux vi /etc/selinux/config 内容修改为: selinux=d ...

  8. 超级详细的iptable教程文档

    Iptabels是与Linux内核集成的包过滤防火墙系统,几乎所有的linux发行版本都会包含Iptables的功能.如果 Linux 系统连接到因特网或 LAN.服务器或连接 LAN 和因特网的代理 ...

  9. Kernel Methods (3) Kernel Linear Regression

    Linear Regression 线性回归应该算得上是最简单的一种机器学习算法了吧. 它的问题定义为: 给定训练数据集\(D\), 由\(m\)个二元组\(x_i, y_i\)组成, 其中: \(x ...

  10. C#-WinForm-布局-Anchor-锁定布局、Dock-填充布局、工具箱中的<容器>

    Anchor - 锁定布局,锁定控件对于其父控件或窗体的位置,保持与边框固定的距离还是居中等 Dock - 填充布局,控件是否如何进行填充 ============================== ...