前言:这是笔者学习之后自己的理解与整理。如果有错误或者疑问的地方,请大家指正,我会持续更新!

事件流

  当浏览器发展到第四代时(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 事件流的更多相关文章

  1. HTML 事件(三) 事件流与事件委托

    本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...

  2. 浅析JavaScript事件流——冒泡

    一.什么是事件冒泡流 我们知道事件流指的是从页面中接受事件的顺序. 为了形象理解事件冒泡,可以想象三军主将诸葛亮,在帐内运筹帷幄,眼观六路耳听八方,这时候前方的战事情况就需要靠传令兵来传达,当第一位传 ...

  3. js事件流

    event:事件对象,当一个事件发生的时候,和当前这个对象发生的这个事件有关的一些详细的信息都会被临时保存在一个指定地方-event对象,供我们在需要调用.event对象必须是在一个事件调用的函数里 ...

  4. javaScript事件(一)事件流

    一.事件 事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字.事件是javaScript和DOM之间的桥梁.你若触发,我便执行——事件发生,调用它的处理函数 ...

  5. 理解DOM事件流的三个阶段

    本文主要解决两个问题: 1.什么是事件流 2.DOM事件流的三个阶段 事件流之事件冒泡与事件捕获 在浏览器发展的过程中,开发团队遇到了一个问题.那就是页面中的哪一部分拥有特定的事件? 可以想象画在一张 ...

  6. 深入理解DOM事件机制系列第一篇——事件流

    × 目录 [1]历史 [2]事件冒泡 [3]事件捕获[4]事件流 前面的话 javascript操作CSS称为脚本化CSS,而javascript与HTML的交互是通过事件实现的.事件就是文档或浏览器 ...

  7. 事件流之事件冒泡与事件捕获<JavaScript高级程序设计>学习笔记

    1.事件流 浏览器开发团队遇到一个很有意思问题:页面的那一部分会拥有特定的事件? 对于理解这个问题您可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上 ...

  8. DOM事件揭秘-事件流

    事件:文档/窗口中发生的特定的交互瞬间 瀑布流,图片轮播 动作都是通过事件触发的 课程内容: 1,理解事件流 2,使用时间处理程序 3,不同的事件类型 ie4.0以后, 事件流:描述的是从页面中接收事 ...

  9. [DOM Event Learning] Section 4 事件分发和DOM事件流

    [DOM Event Learning] Section 4 事件分发和DOM事件流 事件分发机制: event dispatch mechanism. 事件流(event flow)描述了事件对象在 ...

随机推荐

  1. redis慢日志

    redis的slowlog是redis用于记录记录慢查询执行时间的日志系统.由于slowlog只保存在内存中,因此slowlog的效率很高,完全不用担心会影响到redis的性能.Slowlog是Red ...

  2. 如何使用一次for循环得到数组中第二大的数和第三大的数

    装载声明:http://blog.csdn.net/lxsmk9059/article/details/77920206?locationNum=1&fps=1 ,,,,,,,,}; ]; ] ...

  3. C语言描述二叉树的实现及操作(链表实现)

    概述     二叉树为每个节点最多有两个儿子节点(左儿子节点和右儿子节点)的树. 前序遍历:根结点 ---> 左子树 ---> 右子树. 中序遍历:左子树---> 根结点 ---&g ...

  4. Android权限Uri.parse的几种用法(转载)

    1,调web浏览器 Uri myBlogUri = Uri.parse("http://xxxxx.com"); returnIt = new Intent(Intent.ACTI ...

  5. hihocoder [Offer收割]编程练习赛52 D 部门聚会

    看了题目的讨论才会做的 首先一点,算每条边(u, v)对于n*(n+1)/2种[l, r]组合的贡献 正着算不如反着算 哪些[l, r]的组合没有包含这条边(u, v)呢 这个很好算 只需要统计u这半 ...

  6. 攻防组网之—-MikroTik软路由的配置和FUZZ

    作者:红发香克斯 开篇之前一直想借助一台高性能PC利用VMWare组建一个攻防网络,之前有一贴写过找到了一个软路由系统,就是可以在VMWare中使用的路由器操作系统,那个系统还挺常用,上次帖子写到了安 ...

  7. Spring中配置数据源常用的形式

    不管采用何种持久化技术,都需要定义数据源.Spring中提供了4种不同形式的数据源配置方式: spring自带的数据源(DriverManagerDataSource),DBCP数据源,C3P0数据源 ...

  8. 使用.NET开发AutoCAD——C#/AutoCAD 2018/ObjectArx/二次开发入门(二)

    1.开发环境配置: (1)安装AutoCAD2018: (2)安装VS2015: (3)安装ObjectARX 2018类库: (4)安装ObjectARX 2018 .NET开发向导(ObjectA ...

  9. Leetcode 17.——Letter Combinations of a Phone Number

    Given a digit string, return all possible letter combinations that the number could represent. A map ...

  10. vim的配置

    修改根目录下.vimrc文件: 1.设定解码,支持中文 set fileencodings=utf-8,ucs-born,gb18030,gbk,gb2312,cp936 set termencodi ...