jacascript 事件流
前言:这是笔者学习之后自己的理解与整理。如果有错误或者疑问的地方,请大家指正,我会持续更新!
事件流
当浏览器发展到第四代时(IE4及Netscape4),浏览器开发团队遇到了一个很有意思的问题:页面的哪一部分会拥有某个特定的事件?想象画在一张纸上的一组同心圆。如果把手指放在圆心上,那么手指指向的不是一个圆,而是纸上的所有圆。
两家公司的浏览器开发团队在看待浏览器事件方面还是一致的。如果单击了某个按钮,他们都认为单击事件不仅仅发生在按钮上,甚至也单击了整个页面。
但有意思的是,IE 和 Netscape 开发团队居然提出了差不多是完全相反的事件流的概念。IE 的事件流是事件冒泡流,而 Netscape 的事件流是事件捕获流。
事件流又称为事件传播,描述的是从页面中接收事件的顺序。DOM2 级事件规定的事件流包括三个阶段:事件捕获阶段(capture phase)、处于目标阶段(target phase)和事件冒泡阶段(bubbling phase)。
首先发生的是事件捕获,为截获事件提供了机会。然后是实际的目标接收到事件,最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。
默认是在冒泡阶段对事件做出响应。
事件冒泡
IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到 window 对象;
所有现代浏览器都支持事件冒泡,但在具体实现在还是有一些差别。IE9、Firefox、Chrome、Safari将事件一直冒泡到 window 对象;
事件捕获
事件捕获的思想是 window 对象应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前就捕获它;
addEventListener() 方法中的第三个参数是指在冒泡阶段还是捕获阶段处理事件处理程序,设置为 true 时,即为捕获阶段,默认为 false 冒泡阶段;

HTML事件处理程序
某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的 HTML 特性来指定。这个特性的值应该是能够执行的 javascript 代码;
在事件处理程序函数内部,this值等于事件的目标元素;
缺点1:因为用户可能会有HTML元素一出现在页面上时就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件,就会报错;
缺点2:客户端编程的通用风格是保持 HTML 内容和 javaScript 行为分离,所以应该避免使用 HTML 事件处理程序属性,因为这些属性直接混合了 javascript 和 HTML,且不易扩展;
DOM0级事件处理程序
通过 javascript 指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。这种为事件处理程序赋值的方法是在第四代Web浏览器中出现的,而且至今仍然为所有现代浏览器所支持。原因一是简单,二是具有跨浏览器的优势。
每个元素都有自己的事件处理程序属性,这些属性通常全部小写,将这种属性的值设置为一个函数,就可以指定事件处理程序。
以DOM0级方式添加的事件处理程序会在事件流的冒泡阶段被处理;
可以通过将事件处理程序属性设置为 null 来删除事件处理程序;
缺点:DOM0级事件处理程序的缺点是围绕着每个事件目标对于每种事件类型只能添加一个事件处理程序。
<div id="box" style="height:30px;width:200px;background-color:pink;"></div>
<script>
var oBox = document.getElementById('box');
oBox.onclick = function(){
this.innerHTML += 'DOM0级事件处理程序';
}
</script>
DOM2级事件处理程序
DOM2级事件处理程序定义了两个方法用于处理指定和删除事件处理程序的操作:addEventListener() 和 removeEventListener()。IE8及以下浏览器不支持DOM2级事件处理程序。
使用DOM2级事件处理程序的好处是可以添加多个事件处理程序,并按照他们添加的顺序触发;
<div id="box" style="height:200px;width:200px;background-color:pink;"></div>
<script>
var oBox = document.getElementById('box');
oBox.addEventListener('click',function(){
this.innerHTML += '使用DOM2级事件处理程序的好处是可以添加多个事件处理程序<br/>';
});
oBox.addEventListener('click',function(){
this.innerHTML += '并按照他们添加的顺序触发,第三个参数默认为false,所以是事件冒泡的顺序';
});
</script>
所有DOM节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。
最后的布尔值参数如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。若最后的布尔值不填写,则默认为 false。
<div id="box" style="height:200px;width:200px;background-color:pink;">
<div id="child" style="height: 100px;width: 100px;background-color: green;"></div>
</div>
<script>
var oBox = document.getElementById('box');
var oChild = document.getElementById('child');
oBox.addEventListener('click',function(){
console.log('事件捕获顺序 先oBox');
},true);
oChild.addEventListener('click',function(){
console.log('事件捕获顺序 后oChild');
},true);
</script>
若最后的布尔值不填写,则和 false 效果一样。
<script>
var oBox = document.getElementById('box');
var oChild = document.getElementById('child');
oBox.addEventListener('click',function(){
console.log('事件冒泡顺序 后oBox');
});
oChild.addEventListener('click',function(){
console.log('事件冒泡顺序 先oChild');
});
</script>
通过 addEventListener() 添加的事件处理程序只能使用 removeEventListener() 来移除,移除时传入的参数与添加处理程序时使用的参数相同。addEventListener() 添加的匿名函数将无法移除;
<div id="box" style="height:200px;width:200px;background-color:pink;"></div>
<script>
var oBox = document.getElementById('box');
oBox.addEventListener("click",function(){
this.innerHTML += 'removeEventListener()无法移除匿名函数';
},false);
oBox.removeEventListener('click',function(){
this.innerHTML += 'removeEventListener()无法移除匿名函数';
},false);
</script>
IE事件处理程序
IE实现了与DOM中类似的两个方法:attachEvent() 和 detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。由于IE8及以下浏览器只支持事件冒泡,所以通过 attachEvent() 添加的事件处理程序都会被添加到事件冒泡阶段;
attachEvent() 方法的第一个参数是"onclick",而非DOM的 addEventListener()方法中的"click";
与其他三个事件处理程序不同,IE事件处理程序的 this 指向 window,而非被绑定事件的元素;
使用 attachEvent() 方法添加的事件处理程序的触发顺序是有区别的。IE9、10浏览器是按正序执行的,而IE8及以下浏览器则是按倒序执行的;
<div id="box" style="height:30px;width:200px;background-color:pink;"></div>
<script>
var oBox = document.getElementById('box');
oBox.attachEvent('onclick',function(){
this.innerHTML += 'attachEvent()方法的第一个参数是"onclick"'; //与其他三个事件处理程序不同,IE事件处理程序的this指向window,而非被绑定事件的元素
console.log(this);//window
})
</script>
使用 attachEvent() 添加的事件可以通过 detachEvent() 来移除,条件是必须提供相同的参数。与DOM2级事件处理程序一样,这也意味着添加的匿名函数将不能被移除。不过,只要能够将对相同函数的引用传给 detachEvent(),就可以移除相应的事件处理程序。
<div id="box" style="height:30px;width:200px;background-color:pink;"></div>
<script>
var oBox = document.getElementById('box');
oBox.attachEvent("onclick",function(){
box.innerHTML += '与DOM2级事件处理程序一样,attachEvent添加的匿名函数将不能被移除';
},false);
oBox.detachEvent('onclick',function(){
box.innerHTML += '与DOM2级事件处理程序一样,attachEvent添加的匿名函数将不能被移除';
},false);
</script>
事件执行顺序
如果同时出现 HTML 事件处理程序和 DOM0 级事件处理程序,DOM0 级会覆盖 HTML 事件处理程序;
chrome/opera/safari等 webkit 内核的浏览器会按照事件处理程序出现的顺序来排列,所以结果为:DOM2级 DOM0级
firefox 浏览器和 IE 浏览器会将 DOM0 级事件优先调用,所以 firefox 和 IE11 浏览器结果为:DOM0级 DOM2级
IE9、10浏览器结果为:DOM0级 DOM2级 IE
IE8及以下浏览器结果为:DOM0级 IE
jacascript 事件流的更多相关文章
- HTML 事件(三) 事件流与事件委托
本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...
- 浅析JavaScript事件流——冒泡
一.什么是事件冒泡流 我们知道事件流指的是从页面中接受事件的顺序. 为了形象理解事件冒泡,可以想象三军主将诸葛亮,在帐内运筹帷幄,眼观六路耳听八方,这时候前方的战事情况就需要靠传令兵来传达,当第一位传 ...
- js事件流
event:事件对象,当一个事件发生的时候,和当前这个对象发生的这个事件有关的一些详细的信息都会被临时保存在一个指定地方-event对象,供我们在需要调用.event对象必须是在一个事件调用的函数里 ...
- javaScript事件(一)事件流
一.事件 事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字.事件是javaScript和DOM之间的桥梁.你若触发,我便执行——事件发生,调用它的处理函数 ...
- 理解DOM事件流的三个阶段
本文主要解决两个问题: 1.什么是事件流 2.DOM事件流的三个阶段 事件流之事件冒泡与事件捕获 在浏览器发展的过程中,开发团队遇到了一个问题.那就是页面中的哪一部分拥有特定的事件? 可以想象画在一张 ...
- 深入理解DOM事件机制系列第一篇——事件流
× 目录 [1]历史 [2]事件冒泡 [3]事件捕获[4]事件流 前面的话 javascript操作CSS称为脚本化CSS,而javascript与HTML的交互是通过事件实现的.事件就是文档或浏览器 ...
- 事件流之事件冒泡与事件捕获<JavaScript高级程序设计>学习笔记
1.事件流 浏览器开发团队遇到一个很有意思问题:页面的那一部分会拥有特定的事件? 对于理解这个问题您可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上 ...
- DOM事件揭秘-事件流
事件:文档/窗口中发生的特定的交互瞬间 瀑布流,图片轮播 动作都是通过事件触发的 课程内容: 1,理解事件流 2,使用时间处理程序 3,不同的事件类型 ie4.0以后, 事件流:描述的是从页面中接收事 ...
- [DOM Event Learning] Section 4 事件分发和DOM事件流
[DOM Event Learning] Section 4 事件分发和DOM事件流 事件分发机制: event dispatch mechanism. 事件流(event flow)描述了事件对象在 ...
随机推荐
- 【Python】 子进程创建与使用subprocess
subprocess *****本文参考了Vamei大神的http://www.cnblogs.com/vamei/archive/2012/09/23/2698014.html 运用subproce ...
- linq分组求和_实体类和datatable
1.数据分组求合,分别用的实体类以及datatable来分组求合,还有分组求和之后的如何取值 //实体类版本 List<ProgramTimeModel> TotalAllList = G ...
- g第十四周,十五周作业
1.数组中偶数的和 #include <stdio.h> int main(){ ; ]; ;i<=;i++) { scanf("%d ",&a[i]); ...
- Win7(64Bit旗舰版) 安装 PL/SQL Developer图解说明
Win7逐渐成为现行主流的windows操作系统,其32和64位系统平分秋色.然而当下还没有64位的PL/SQL Developer问世,直接用32位的PL/SQL Developer连接Win7(6 ...
- 【Alpha 阶段】后期测试及补充(第十一、十二周)
[Alpha 阶段]动态成果展示 修复了一些bug后,关于游戏的一些动态图展示如下: 终极版需求规格说明书和代码规范 经过一些细微的图片和格式的调整,完成了本学期的最终版本: [markdown版说明 ...
- WORK
团队展示 队伍信息 队名:小狗队 队长:刘映华(201421122021) 队员:兰运良(201421122030).郭和水(201421122017) 团队项目描述 团队项目描述是基于之前的四则运算 ...
- RxSwift(一)
文/iOS_Deve(简书作者) 原文链接:http://www.jianshu.com/p/429b5160611f 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者" ...
- bzoj千题计划274:bzoj3779: 重组病毒
http://www.lydsy.com/JudgeOnline/problem.php?id=3779 有一棵树,初始每个节点有不同的颜色 操作1:根节点到x的路径上的点 染上一种没有出现过的颜色 ...
- python之路--day6--字符编码
一.知识储备 cpu--控制和运算 内存--暂时存储cpu需要的数据 硬盘--永久保存数据2.文本编辑器的原理存储原理 1,启动文本编辑器 2,在编辑器上输入内容---此时输入内容还在内存上 3,保存 ...
- JAVA_SE基础——41.instanceof关键字(运算符)
instanceof 关键字 instanceof关键字的作用:判断一个对象是否属于指定的类别. instanceof关键字的使用前提:判断的对象与指定的类别必须要存在继承或者实现的关系.关于实现以后 ...