JavaScript事件学习小结(一)事件流


Posted in Javascript onJune 09, 2016

相关阅读:

JavaScript事件学习小结(五)js中事件类型之鼠标事件

JavaScript事件学习小结(一)事件流 JavaScript事件学习小结(一)事件流 JavaScript事件学习小结(一)事件流

2、事件流

事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。

事件传播的顺序对应浏览器的两种事件流模型:捕获型事件流和冒泡型事件流。

冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。即从DOM树的叶子到根。

捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。即从DOM树的根到叶子。

<!DOCTYPE html>
<html>
<head lang="en">
 <meta charset="UTF-8">
 <title></title>
</head>
<body>
<div id="myDiv">Click me!</div>
</body>
</html>

上面这段html代码中,单击了页面中的<div>元素,

在冒泡型事件流中click事件传播顺序为<div>—》<body>—》<html>—》document

在捕获型事件流中click事件传播顺序为document—》<html>—》<body>—》<div>

JavaScript事件学习小结(一)事件流JavaScript事件学习小结(一)事件流

note:

1)、所有现代浏览器都支持事件冒泡,但在具体实现中略有差别:

IE5.5及更早版本中事件冒泡会跳过<html>元素(从body直接跳到document)。

IE9、Firefox、Chrome、和Safari则将事件一直冒泡到window对象。

2)、IE9、Firefox、Chrome、Opera、和Safari都支持事件捕获。尽管DOM标准要求事件应该从document对象开始传播,但这些浏览器都是从window对象开始捕获事件的。

3)、由于老版本浏览器不支持,很少有人使用事件捕获。建议使用事件冒泡。

DOM事件流

DOM标准采用捕获+冒泡。两种事件流都会触发DOM的所有对象,从document对象开始,也在document对象结束。

JavaScript事件学习小结(一)事件流

DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。

事件捕获阶段:实际目标(<div>)在捕获阶段不会接收事件。也就是在捕获阶段,事件从document到<html>再到<body>就停止了。上图中为1~3.

处于目标阶段:事件在<div>上发生并处理。但是事件处理会被看成是冒泡阶段的一部分。

冒泡阶段:事件又传播回文档。

note:

1):DOM标准规定事件捕获阶段捕获涉及事件目标,但是在IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都会在捕获阶段出发事件对象上的事件。结果,就是有两次机会在目标对象上面操作事件。

2):并非所有的事件都会经过冒泡阶段 。所有的事件都要经过捕获阶段和处于目标阶段,但是有些事件会跳过冒泡阶段:如,获得输入焦点的focus事件和失去输入焦点的blur事件。

两次机会在目标对象上面操作事件例子:

<!DOCTYPE html>
<html>
<head lang="en">
 <meta charset="UTF-8">
 <title></title>
</head>
<style>
 #outer{
 position: absolute;
 width: 400px;
 height: 400px;
 top:0;
 left: 0;
 bottom:0;
 right: 0;
 margin: auto;
 background-color: deeppink;
 }
 #middle{
 position: absolute;
 width: 300px;
 height:300px;
 top:50%;
 left: 50%;
 margin-left: -150px;
 margin-top: -150px;
 background-color: deepskyblue;
 }
 #inner{
 position: absolute;
 width: 100px;
 height:100px;
 top:50%;
 left:50%;
 margin-left: -50px;
 margin-top: -50px;;
 background-color: darkgreen;
 text-align: center;
 line-height: 100px;
 color:white;
 }
 #outer,#middle,#inner{
 border-radius:100%;
 }
</style>
<body>
<div id="outer">
 <div id="middle">
 <div id="inner">
 click me!
 </div>
 </div>
</div>
<script>
 var innerCircle= document.getElementById("inner");
 innerCircle.addEventListener("click", function () {
 alert("innerCircle的click事件在捕获阶段被触发");
 },true);
 innerCircle.addEventListener("click", function () {
 alert("innerCircle的click事件在冒泡阶段被触发");
 },false);
 var middleCircle= document.getElementById("middle");
 middleCircle.addEventListener("click", function () {
 alert("middleCircle的click事件在捕获阶段被触发");
 },true);
 middleCircle.addEventListener("click", function () {
 alert("middleCircle的click事件在冒泡阶段被触发");
 },false);
 var outerCircle= document.getElementById("outer");
 outerCircle.addEventListener("click", function () {
 alert("outerCircle的click事件在捕获阶段被触发");
 },true);
 outerCircle.addEventListener("click", function () {
 alert("outerCircle的click事件在冒泡阶段被触发");
 },false);
</script>
</body>
</html>

运行效果就是会陆续弹出6个框,为说明原理我整合成了一个图:

JavaScript事件学习小结(一)事件流

3、事件流的典型应用——事件代理

传统的事件处理中,需要为每个元素添加事件处理器。js事件代理则是一种简单有效的技巧,通过它可以把事件处理器添加到一个父级元素上,从而避免把事件处理器添加到多个子级元素上。

事件代理的原理用到的就是事件冒泡和目标元素,把事件处理器添加到父元素,等待子元素事件冒泡,并且父元素能够通过target(IE为srcElement)判断是哪个子元素,从而做相应处理。关于target更多内容请参考javaScript事件学习小结(四)event的公共成员(属性和方法)下面举例来说明。

传统事件处理,为每个元素添加事件处理器,代码如下:

<body>
<ul id="color-list">
<li>red</li>
<li>orange</li>
<li>yellow</li>
<li>green</li>
<li>blue</li>
<li>indigo</li>
<li>purple</li>
</ul>
<script>
(function(){
 var colorList=document.getElementById("color-list");
 var colors=colorList.getElementsByTagName("li");
 for(var i=0;i<colors.length;i++)
 {
 colors[i].addEventListener('click',showColor,false);
 };
 function showColor(e)
 {
 e=e||window.event;
 var targetElement=e.target||e.srcElement;
 alert(targetElement.innerHTML);
 }
})();
</script>
</body>

事件代理的处理方式,代码如下:

<body>
<ul id="color-list">
<li>red</li>
<li>orange</li>
<li>yellow</li>
<li>green</li>
<li>blue</li>
<li>indigo</li>
<li>purple</li>
</ul>
<script>
(function(){
 var colorList=document.getElementById("color-list");
 colorList.addEventListener('click',showColor,false);
 function showColor(e)
 {
 e=e||window.event;
 var targetElement=e.target||e.srcElement;
 if(targetElement.nodeName.toLowerCase()==="li"){
 alert(targetElement.innerHTML);
 }
 }
})();
</script>
</body>

总结一下事件代理的好处:

a、将多个事件处理器减少到一个,因为事件处理器要驻留内存,这样就提高了性能。想象如果有一个100行的表格,对比传统的为每个单元格绑定事件处理器的方式和事件代理(即table上添加一个事件处理器),不难得出结论,事件代理确实避免了一些潜在的风险,提高了性能。

b、DOM更新无需重新绑定事件处理器,因为事件代理对不同子元素可采用不同处理方法。如果新增其他子元素(a,span,div等),直接修改事件代理的事件处理函数即可,不需要重新绑定处理器,不需要再次循环遍历。

以上所述是小编给大家介绍的JavaScript事件学习小结(一)事件流的相关知识,希望对大家有所帮助!

Javascript 相关文章推荐
javascript事件问题
Sep 05 Javascript
33个优秀的jQuery 教程分享(幻灯片、动画菜单)
Jul 08 Javascript
innerText和textContent对比及使用介绍
Feb 27 Javascript
Vuex之理解Getters的用法实例
Apr 19 Javascript
JS实现获取汉字首字母拼音、全拼音及混拼音的方法
Nov 14 Javascript
js时间戳与日期格式之间相互转换
Dec 11 Javascript
通过jquery toggleClass()属性制作文章段落更改背景颜色
May 21 jQuery
使用vue-router为每个路由配置各自的title
Jul 30 Javascript
JavaScript中Array方法你该知道的正确打开方法
Sep 11 Javascript
使用webpack构建应用的方法步骤
Mar 04 Javascript
electron踩坑之remote of undefined的解决
Oct 06 Javascript
解决iview table组件里的 固定列 表格不自适应的问题
Nov 13 Javascript
JavaScript事件学习小结(五)js中事件类型之鼠标事件
Jun 09 #Javascript
基于JS如何实现类似QQ好友头像hover时显示资料卡的效果(推荐)
Jun 09 #Javascript
JS实现星星评分功能实例代码(两种方法)
Jun 09 #Javascript
Node.js中npm常用命令大全
Jun 09 #Javascript
jQuery EasyUI框架中的Datagrid数据表格组件结构详解
Jun 09 #Javascript
Active控件问题小结(附解决办法)
Jun 09 #Javascript
JS 通过系统时间限定动态添加 select option的实例代码
Jun 09 #Javascript
You might like
使PHP自定义函数返回多个值
2006/11/26 PHP
thinkphp文件处理类Dir.class.php的用法分析
2014/12/08 PHP
php安装ssh2扩展的方法【Linux平台】
2016/07/20 PHP
PHP面向对象程序设计之对象的遍历操作示例
2019/06/12 PHP
学习ExtJS table布局
2009/10/08 Javascript
JavaScript实现点击单选按钮改变输入框中文本域内容的方法
2015/08/12 Javascript
jQuery实现点击按钮弹出可关闭层的浮动层插件
2015/09/19 Javascript
如何让一个json文件显示在表格里【实现代码】
2016/05/09 Javascript
BootStrap 可编辑表Table格
2016/11/24 Javascript
jquery.guide.js新版上线操作向导镂空提示jQuery插件(推荐)
2017/05/20 jQuery
JavaScript实现异步图像上传功能
2018/07/12 Javascript
微信小程序http连接访问解决方案的示例
2018/11/05 Javascript
[03:28]2014DOTA2国际邀请赛 EG战队官方纪录片
2014/07/21 DOTA
浅析Python中yield关键词的作用与用法
2016/11/29 Python
Python 3.x 安装opencv+opencv_contrib的操作方法
2018/04/02 Python
Python中shapefile转换geojson的示例
2019/01/03 Python
python制作图片缩略图
2019/04/30 Python
python批量图片处理简单示例
2019/08/06 Python
如何基于Python获取图片的物理尺寸
2019/11/25 Python
python pprint模块中print()和pprint()两者的区别
2020/02/10 Python
Python3 操作 MySQL 插入一条数据并返回主键 id的实例
2020/03/02 Python
Python实现转换图片背景颜色代码
2020/04/30 Python
13个Pandas实用技巧,助你提高开发效率
2020/08/19 Python
俄罗斯眼镜网: optikaworld
2016/07/31 全球购物
Calphalon美国官网:美国顶级锅具品牌
2020/02/05 全球购物
初入社会应届生求职信
2013/11/18 职场文书
保安拾金不昧表扬信
2014/01/15 职场文书
《秋游》教学反思
2014/04/24 职场文书
药剂专业自荐书
2014/06/20 职场文书
校园环保广播稿(3篇)
2014/09/15 职场文书
公司授权委托书范文
2014/09/21 职场文书
小型婚礼主持词
2015/06/30 职场文书
详细总结Python常见的安全问题
2021/05/21 Python
Nginx部署vue项目和配置代理的问题解析
2021/08/04 Servers
vue使用Google Recaptcha验证的实现示例
2021/08/23 Vue.js
Linux服务器离线安装 nginx的详细步骤
2022/06/16 Servers