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)描述了事件对象在 ...
随机推荐
- thinkphp5 taglib自定义标签教程
学着写了一下,终于搞定了,顺便分享一下!taglib是tp框架自定义标签功能,如果你用过cms,肯定见过类似: {dede:arclist typeid='' row='' col='' titlel ...
- python中super()的一些用法
在看python高级编程这本书的时候,在讲到super的时候,产生了一些疑惑,super在python中的用法跟其他的语言有一些不一样的地方,在网上找了一些资料,发现基本上很少有文章能把我的疑惑讲明白 ...
- 开源一个定时任务调度器 webscheduler
在企业应用中定时任务调度的需求是必不可少的,比如定时同步数据,定时结转数据,定时检测异常等等.公司之前是在使用一款采用.net 开发的windows服务形式的定时程序,基本能满足需求,在一段时间的时候 ...
- 【itchat】用Python玩耍微信
[itchat] itchat是个基于网页版微信的python微信API.功能目前做到基本可以满足正常的消息收发,信息的获取等等.不过对于红包之类网页版微信不支持的功能,这个模块自然也就无法支持了. ...
- Android Service基础
Service Service 是一个组件,用来执行长时间的后台操作,不提供用户界面. 另一个应用组件可以启动一个Service,它将持续地在后台运行,即便是用户转移到另一个应用它也不会停止. 另外, ...
- DataTables ajax + bootstrap 分页/搜索/排序/常见问题
最近学校的网站建设需要,尝试使用了下Jquery dataTables控件,接触过C#的人都知道,C#中也含有一个DataTable,但它和我们今天讨论的东西无关 我使用的是官网最新的DataTabl ...
- 初始配置JDK
什么是java? java是一门编程语言 编程语言有很多种 你比如 C语言 等等 为什么学习java呢! 因为你要和计算机交互 当然了你用汉语跟她说她听不懂 所以你要学习编程语言 那么额咱们的ja ...
- python全栈开发-Day12 三元表达式、函数递归、匿名函数、内置函数
一. 三元表达式 一 .三元表达式 仅应用于: 1.条件成立返回,一个值 2.条件不成立返回 ,一个值 def max2(x,y): #普通函数定义 if x > y: return x els ...
- Beta 第四天
今天遇到的困难: 百度位置假死的问题研究发现并不是源于代码的问题,而是直接运行在主线程中会出现诸多问题 Fragment碎片刷新时总产生的固定位置的问题未果 今天完成的任务: 陈甘霖:修复了部分Bug ...
- 学号:201621123032 《Java程序设计》第13周学习总结
1:本周学习总结 2:为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 2.1:简述你想为你的系统增加什么网络功能?设计思路是什么? 创建了一个服务器监听8080端口,通过网络助手客户 ...