js的事件流你真的弄明白了吗?
当浏览器发展到第四代时候,浏览器开发团队遇到了一个有意思的问题;页面的哪一部分会拥有某个特地的事件?要明白这个问题问的是什么,可以想象画在纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的不是一个圆,而是纸上所有的圆。两家公司的开发团队在这件事情上的看法是一致的,如果你单击了某个按钮,他们都认为单击事件不仅发生在按钮上,更是发生在了整个容器元素,甚至是整个页面。
那么对于页面接收事件的顺序两者出现了不同的定义:捕获流 ( chrome )冒泡流( IE )。在事件监听addEventListener的第三个参数中,捕获流是 true,冒泡流是 false。主流浏览器默认的都是冒泡流机制,也就是第三个参数默认false。
事件捕获:window -> document -> html -> body -> button (原先的‘DOM2级事件’本来是规定事件应该从document对象出发的,但是后面几乎所有的浏览器还是拓展到了window对象层面)
事件冒泡:button -> body -> html -> document -> window
事实上‘DOM2级事件’规定的事件流包括了三个阶段: 事件捕获阶段,处于目标阶段,事件冒泡阶段。(原先是规定捕获阶段不涉及事件目标的,但是后面高版本都会在捕获阶段触发事件对象上的事件)
重点:处于目标阶段,即button的事件在捕获阶段和冒泡阶段都会被触发。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.box
{
position: relative;
background-color: coral;
border: 1px solid;
padding: 50px;
}
.child {
position: relative;
background-color: pink;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<div id="A" class="box">
<div id="B">
<div id="C" class="child">点击该方块, 我是冒泡</div>
</div>
</div><br>
<script>
document.getElementById("A").addEventListener("click", function(e)
{
console.log("1 捕获");
}, true);
document.getElementById("B").addEventListener("click", function(e)
{
console.log("2 捕获");
// e.stopPropagation()
}, true);
document.getElementById("C").addEventListener("click", function(e)
{
console.log("捕获阶段触发目标");
// e.stopPropagation()
}, true);
document.getElementById("C").addEventListener("click", function()
{
console.log("冒泡触发目标");
}, false);
document.getElementById("B").addEventListener("click", function()
{
console.log("1 冒泡");
}, false);
document.getElementById("A").addEventListener("click", function()
{
console.log("2 冒泡");
}, false); </script> </body>
</html>
执行结果如下:

值得注意的是,捕获阶段或者冒泡阶段对应的在 C 上的事件其实并不是 先捕获阶段触发目标 然后是冒泡阶段触发目标,在C上的事件其实是都是触发的,触发顺序取决于你写的顺序。不信,换下顺序如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.box
{
position: relative;
background-color: coral;
border: 1px solid;
padding: 50px;
}
.child {
position: relative;
background-color: pink;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<div id="A" class="box">
<div id="B">
<div id="C" class="child">点击该方块, 我是冒泡</div>
</div>
</div><br>
<script>
document.getElementById("A").addEventListener("click", function(e)
{
console.log("1 捕获");
}, true);
document.getElementById("B").addEventListener("click", function(e)
{
console.log("2 捕获");
// e.stopPropagation()
}, true);
document.getElementById("C").addEventListener("click", function()
{
console.log("冒泡触发目标");
}, false);
document.getElementById("C").addEventListener("click", function(e)
{
console.log("捕获阶段触发目标");
// e.stopPropagation()
}, true); document.getElementById("B").addEventListener("click", function()
{
console.log("1 冒泡");
}, false);
document.getElementById("A").addEventListener("click", function()
{
console.log("2 冒泡");
}, false); </script> </body>
</html>
执行结果如下:

接下来继续说一下阻止冒泡,假设我在 console.log("1 捕获") 或者 console.log("2 捕获") 后面加上 e.stopPropagation(),后面的事件还能触发吗?单单是只把冒泡流扼杀了吗?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.box
{
position: relative;
background-color: coral;
border: 1px solid;
padding: 50px;
}
.child {
position: relative;
background-color: pink;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<div id="A" class="box">
<div id="B">
<div id="C" class="child">点击该方块, 我是冒泡</div>
</div>
</div><br>
<script>
document.getElementById("A").addEventListener("click", function(e)
{
console.log("1 捕获");
e.stopPropagation()
}, true);
document.getElementById("B").addEventListener("click", function(e)
{
console.log("2 捕获"); }, true);
document.getElementById("C").addEventListener("click", function()
{
console.log("冒泡触发目标");
}, false);
document.getElementById("C").addEventListener("click", function(e)
{
console.log("捕获阶段触发目标");
// e.stopPropagation()
}, true); document.getElementById("B").addEventListener("click", function()
{
console.log("1 冒泡");
}, false);
document.getElementById("A").addEventListener("click", function()
{
console.log("2 冒泡");
}, false); </script> </body>
</html>

事实上,它是把后面的事件流都打断了。而如果 e.stopPropagation() 是写在 console.log("捕获阶段触发目标") 或者 console.log("冒泡触发目标")后面,目标阶段都点击事件都会执行,执行按你写的顺序来。
Propagation英文意思是‘传播’ stopPropagation 就是阻止事件传播,阻止事件流的继续往下发生。
所以stopPropagation()方法事实上是打断了事件流继续执行,而我们一般时候是直接写在目标事件的点击函数里,就起到了阻止冒泡的作用!
js的事件流你真的弄明白了吗?的更多相关文章
- js的事件流理解
面试问到js的事件流,当时说的不是很清楚,现在觉得有必要把这个弄清楚. 事件捕获和事件冒泡 事件流描述的是从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序. 事件流主要分为两种,即事件捕获和事 ...
- js基础--javaScript数据类型你都弄明白了吗?绝对干货
欢迎访问我的个人博客:http://www.xiaolongwu.cn 数据类型的分类 JavaScript的数据类型分为两大类,基本数据类型和复杂数据类型. 基本数据类型:Null.Undefine ...
- python 全栈开发,Day55(jQuery的位置信息,JS的事件流的概念(重点),事件对象,jQuery的事件绑定和解绑,事件委托(事件代理))
一.jQuery的位置信息 jQuery的位置信息跟JS的client系列.offset系列.scroll系列封装好的一些简便api. 一.宽度和高度 获取宽度 .width() 描述:为匹配的元素集 ...
- JS Event事件流(冒泡机制、捕获机制、事件绑定)
1.事件流 事件流:从页面中接收事件的顺序.也就是说当一个事件产生时,这个事件的传播过程,就是事件流. IE的事件流 IE中的事件流叫事件冒泡:事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播 ...
- 前端 ----js的事件流的概念(重要)
09-JS的事件流的概念(重点) 在学习jQuery的事件之前,大家必须要对JS的事件有所了解.看下文 事件的概念 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页 ...
- JS的事件流的概念(重点)
09-JS的事件流的概念(重点) 在学习jQuery的事件之前,大家必须要对JS的事件有所了解.看下文 事件的概念 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件 ...
- JS的事件流的概念
事件的概念: HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件.想要知道这些事件是在 ...
- JS的事件流概念*******
事件的概念 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件. 事件流 事件流描述的 ...
- 08 JS的事件流的概念(重点)
在学习jQuery的事件之前,大家必须要对JS的事件有所了解.看下文 事件的概念 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以 ...
随机推荐
- python unix时间戳
这是第一次用着python感到怒了,从datetime转化到timestamp数值居然没有直接的函数 直接获取当前时间戳倒是方便: import time timestamp = time.time( ...
- WinSock Socket 池
之前在WinSock2.0 API 中说到,像DisConnectEx 函数这样,它具有回收SOCKET的功能,而像AcceptEx这样的函数,它不会自己在内部创建新的SOCKET,需要外部传入SOC ...
- oracle学习篇四:多表查询
-----------------产生笛卡儿积------------------------------------ select * from emp,dept; --不带条件时,记录数为14*4 ...
- 【代码笔记】Java——远程监控、反射、代理、内省机制
远程控制的基本原理 远程控制(RemoteControl)拥有控制端和被控端双方. 控制方通过请求,取得对远端的操作,实现远端的事件回放功能,同时,应该看得到远端桌面的画面.而被控方必须在建立Serv ...
- jQuery Mobile 移动 web 应用程序框架
在这里我们主要讲一下如何引用jQuery Mobile(引用了jQuery Mobile,你就能引用jQuery Mobile里已经封装好的代码,让开发更加快捷简单) 从 CDN 引用 jQuery ...
- 增加C盘空间大小
随着我们使用电脑的时间越来越久,电脑C盘的空间会出现不够用的情况,这时我们需要的就是增加C盘的大小,基本上有两种方式 1.通过系统自带的磁盘管理(有可能没法操作,主要介绍第二种) 2.通过分区软件进行 ...
- March 19 2017 Week 12 Sunday
If you want it, work for it. It's that simple. 很简单,想要什么,就为之努力吧. Yes, it is very simple. Many of us j ...
- Kubernetes里的secret最基本的用法
Secret解决了密码.token.密钥等敏感数据的配置问题,使用Secret可以避免把这些敏感数据以明文的形式暴露到镜像或者Pod Spec中. Secret可以以Volume或者环境变量的方式使用 ...
- com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException 异常
MySQL完整性约束破坏异常:com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException 在单向多对一关联关系 ...
- 【[USACO15FEB]审查(黄金)Censoring (Gold)】
从原来的单串匹配变成了多串匹配 好像也没什么特别不一样的地方 原来的做法是搞一个栈,之后一旦匹配到就往前弹栈 做法也一样 但是在\(AC\)自动机上暴力跳\(fail\)是要\(T\)的 我们并没有必 ...