面试整理之DOM事件阶段
因为快面试了,打开《JavaScript高级程序设计》,对DOM事件进行整理了下
本文主要解决的问题:
- 事件流
- DOM事件流的三个阶段
先理解流的概念
在现今的JavaScript中随处可见。比如说React中的单向数据流,Node中的流,又或是今天本文所讲的DOM事件流。都是流的一种生动体现。用术语说流是对输入输出设备的抽象。以程序的角度说,流是具有方向的数据。
事件流分事件冒泡与事件捕获
在浏览器发展的过程中,开发团队遇到了一个问题。那就是页面中的哪一部分拥有特定的事件?
可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上所有的圆。放到实际页面中就是,你点击一个按钮,事实上你还同时点击了按钮所有的父元素。
开发团队的问题就在于,当点击按钮时,是按钮最外层的父元素先收到事件并执行,还是具体元素先收到事件并执行?所以这儿引入了事件流的概念。
通俗说,事件流所描述的就是从页面中接受事件的顺序。
因为有两种观点,所以事件流也有两种,分别是事件冒泡和事件捕获。现主流是事件冒泡。
事件冒泡
事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。
下面写个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Event Bubbling</title>
</head>
<body>
<button id="clickMe">Click Me</button>
</body>
</html>
然后,我们给button和它的父元素,加入点击事件。
var button = document.getElementById('clickMe'); button.onclick = function() {
console.log('1. You click Button');
};
document.body.onclick = function() {
console.log('2. You click body');
};
document.onclick = function() {
console.log('3. You click document');
};
window.onclick = function() {
console.log('4. You click window');
};
在Chrome浏览器运行:
如果点击了button,那么这个点击事件会按如下的顺序传播
- button
- body
- document
- window
也就是说,click事件首先在<button>元素上发生,然后逐级向上传播。
事件捕获
事件捕获的概念,与事件冒泡正好相反。它认为当某个事件发生时,父元素应该更早接收到事件,具体元素则最后接收到事件。比如说刚才的demo,如果是事件捕获的话,事件发生顺序会是这样的:
- window
- document
- body
- button
事件阶段(Event Phases)
当一个DOM事件触发时,它不是在触发的对象上只触发一次的,而是经历三个阶段。分别为
1:一开始从文档的根节点流向目标对象(捕获阶段)
2:然后在目标对向上被触发(目标阶段)
3:之后再回溯到文档的根节点(冒泡阶段).
1. 事件捕获阶段
事件的第一个阶段是捕获阶段。事件从文档的根节点出发,随着DOM树的结构向事件的目标节点流去。途中经过各个层次的DOM节点,并在各节点上触发捕获事件,直到到达事件的目标节点。捕获阶段的主要任务是建立传播路径,在冒泡阶段,事件会通过这个路径回溯到文档跟节点。当事件发生时,首先发生的是事件捕获,为父元素截获事件提供了机会。
例如,我把上面的Demo中,window点击事件更改为使用事件捕获模式。(addEventListener最后一个参数,为true则代表使用事件捕获模式,false则表示使用事件冒泡模式。不理解的可以去学习一下addEventListener函数的使用)
window.addEventListener('click', function() {
console.log('4. You click window');
}, true);
此时,点击button的效果是这样的。
可以看到,点击事件先被父元素截获了,且该函数只在事件捕获阶段起作用。
处于目标与事件冒泡阶段
事件到了具体元素时,在具体元素上发生,并且被看成冒泡阶段的一部分。
随后,冒泡阶段发生,事件开始冒泡。
阻止事件冒泡
事件冒泡过程,是可以被阻止的。防止事件冒泡而带来不必要的错误和困扰。
这个方法就是:stopPropagation()
我们对button的click事件做一些改造。
button.addEventListener('click', function(event) {
// event为事件对象
console.log('1. You click Button');
event.stopPropagation();
console.log('Stop Propagation!');
}, false);
点击后,效果如下图:
不难看出,事件在到达具体元素后,停止了冒泡。但不影响父元素的事件捕获。
总结
事件流:描述的就是从页面中接受事件的顺序。
分有事件冒泡与事件捕获两种。
DOM事件流的三个阶段:
- 事件捕获阶段
- 处于目标阶段
- 事件冒泡阶段
参考资料:《JavaScript高级程序设计》第三版
最新文章
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(64)-WebApi与Unity注入
- cookie禁用了,session还能用吗?
- impdp导入job
- mysql 启动 pid报错解决方法
- CentOS6.4 配置Haproxy
- [SAP ABAP开发技术总结]Form(subroutine)、Function参数传值传址
- 网络配置和NFS和TFTP的配置
- theos初探:ios越狱开发教程
- web架构设计经验分享(转)
- 最简单的排序算法之一冒泡排序----js实现
- Oracle Jdbc驱动下载及安装本地maven仓库
- #include、#import与@class的使用与头文件循环引用问题
- 引号在jsp页面中正确显示的处理
- CSS 文本溢出时显示省略标记
- jq 滚轮监听事件
- 抽象工厂模式(Abstract Factory Pattern)
- liunx 安装jdk1.8
- [ISE 14.7] _pn.exe 崩溃问题 点击浏览崩溃问题
- [实战]MVC5+EF6+MySql企业网盘实战(4)——上传头像
- 家庭记账本之Github账号注册与安装(二)
热门文章
- html表单验证程序
- Visual Studio Online Integrations-Productivity
- Hadoop 2.2.0部署安装(笔记,单机安装)
- 浏览器兼容性小整理和一些js小问题(后面会继续更新)
- 微信5.4你所不知道的事 X5浏览引擎提速50%-80%
- cocos进阶教程(3)Cocos2d-x多场景切换生命周期
- Android程序启动加载动画实现
- PHP中magic_quotes_gpc动态关闭无效的问题
- 【Python】使用 sphinx 制作简洁而又美观的文档
- string s = null 和 string s = “”的区别