MyException - 我的异常网
当前位置:我的异常网» Web前端 » 深入了解IE事件模型与DOM事件模型

深入了解IE事件模型与DOM事件模型

www.MyException.Cn  网友分享于:2013-10-07  浏览:21次
深入理解IE事件模型与DOM事件模型
来源:http://qiqicartoon.com/?p=816
事件模型对于javascript程序员来说太重要了!如果你的javascript中找不到attahEvent或addEventListener的话,那我觉得真的有点太荒唐了(某些项目应该没有事件驱动)。
毫无疑问深入理解事件模型将使你的工作事半功倍!
其实理解事件模型倒也不是很困难,困难之处在于事件模型之前的兼容性!说到这里不得不提起讨厌的IE和喜爱的DOM。
我们知道IE内核的浏览器,它的事件模型是冒泡型事件,也就是说在IE内核下事件句柄的触发顺序是从ChildNode到ParentNode。
1 <div id="ancestor">
2       <button id="child">
3           Open the console and click me
4       </button>
5   </div>

以上的HTML代码在IE内核下,事件是这样传播的:
1、Button#child;
2、div#ancestor;
3、Body;
4、Document
切记!IE的内核是没有捕获事件过程的
那么在DOM标准的浏览器,事件传播的过程又是怎样的呢?我们依然拿上面的HTML代码做例子,在DOM标准的浏览器事件是这样传播的:
1、Window
2、Document
3、Body
4、Div#ancestor
5、Button#child

Bubble

6、Div#ancestor
7、Body
8、Document
9、Window
在DOM标准的浏览器中多了一个事件捕获过程,也就是说当开发者在一个无素上注册了事件后,这个事件的响应顺序是从window(最顶层)开始一级一级的向下传播,然后到了该元素后事件捕获过程结束,事件开如冒泡,一级一级向父层元素冒泡(请注意第6步)。当然了开发者可以很轻松的决定DOM标准的浏览器中的事件需要在哪个传播过程触发这。就需要谈一下事件的注册机制了。
DOM标准的浏览器事件注册方法是通过addEventListener方法注册,而IE内核的浏览器则是通过attachEvent方法注册。
这两个方法的区别,我在此简单的介绍下,若不太明白,可以自行去搜索相关资料。
addEventListener方法带有三个参数,分别是:eventType、handler、useCapture。
eventType不带有on字符串;
handler参数是一个事件句柄,这个函数或方法带有一个事件对象参数;
useCapture参数决定了事件句柄触发在哪种事件传播阶段,如果useCapture为true则为捕获阶段,反之则为冒泡阶段。
是不是还是不太理解捕获阶段和冒泡阶段,不用怕,看以下代码的演示:
我们依然用以上的HTML代码片段
1 var ancestorHandler = function (e){
2   //......
3 },
4 childHandler = function (e){
5   //......
6 };
7 document.querySelector('#ancestor').addEventListener('click',ancestorHandler,false);//注意第三个参数
8 document.querySelector('#child').addEventListener('click',childHandler,true);//注意第三个参数

以上代码我们为div节点注册了一个在冒泡阶段触发的事件句柄,为按钮节点注册了一个在捕获阶段的事件句柄,请注意DIV是按钮的父层。
当用户在这个DIV元素上点击时,事件的执行顺序是childHandler、ancestorHandler。
为什么会是这样呢?这是因为按钮的事件是在捕获阶段触发的,也就是从上到下,而DIV的事件是注册在冒泡阶段,也就是点击了这个按钮开始从这个按钮的位置往上冒泡。
当然了,我们可以阻止事件的冒泡,DOM事件对象提供了stopPropagation方法用于阻止事件流。
1 var ancestorHandler = function (e){
2   //......
3 },
4 childHandler = function (e){
5   e.stopPropagation();
6   //......
7 };


以上代码中我们在childHandler函数中添加了e.stopPropagation()代码片段,它将阻止事件流,事件流包括捕获阶段及冒泡阶段的事件流。
我们再修改上面的代码如下:
1 var ancestorHandler = function (e){
2   //......
3 },
4 childHandler = function (e){
5   //......
6 };
7 document.querySelector('#ancestor').addEventListener('click',ancestorHandler,true);//注意第三个参数
8 document.querySelector('#child').addEventListener('click',childHandler,true);//注意第三个参数

以上的代码产生的结果是:用户在DIV元素上单击时,将会依次触发ancestorHandler、childHandler函数,为什么?因为我们将div#ancestor的事件注册到捕获阶段了,也就是从上至下。当然了我们还可以阻止childHandler方法的执行。
1 var ancestorHandler = function (e){
2   e.stopPropagation();
3   //......
4 },
5 childHandler = function (e){
6   //......
7 };

以上代码将阻止按钮的事件触发。当用户点击了DIV的区域,仅仅触发ancestorHandler函数,因为我们阻止了事件流。
接下来我们看看在IE内核的浏览器中是如何注册事件的。IE内核提供了attachEvent方法为元素注册事件,注意该方法与DOM的addEventListener方法区别很大!该方法带有两个参数,
eventType 事件类型,请注意这个参数与addEventListener的eventType的区别,它必须带有on;
handler 事件句柄
请注意attachEvent没有提供事件捕获阶段的参数,IE内核的事件都是发生在冒泡阶段!
1 var ancestorHandler = function (e){
2   //......
3 },
4 childHandler = function (e){
5   //......
6 };
7 document.getElementById('ancestor').attachEvent('onclick',ancestorHandler);//注意没有第三个参数
8 document.getElementById('child').attachEvent('onclick',childHandler);//注意没有第三个参数

以上代码在IE中将为DIV元素和按钮元素注册了不同的事件。
另外还有一些注意事项:
1、DOM标准的addEventListener方法执行事件的顺序是按照事件注册的顺序执行的。而attachEvent方法则相反–后注册的事件先觖发,先注册的事件后触发。
2、DOM标准的浏览器文本节点也会冒泡,而IE内核的浏览器文本节点不会冒泡。
3、DOM标准的浏览器事件对象与IE内核的浏览器事件不同(具体请参阅http://www.quirksmode.org/js/introevents.html)。
4、DOM标准的浏览器事件卸载方式与IE内核的事件卸载方式不同。
1 object.removeEventListener(eventType,handler,useCapture);//DOM标准的事件卸载方式
2 object.detachEvent(eventType,handler);//IE内核的事件卸载方式

在DOM标准的事件卸载方式中需要注意的是:事件捕获的参数。如果你的事件是注册在捕获阶段,则卸载事件时,必须将其指定为捕获阶段(true),否则无法卸载;如果你的事件注册在注册在冒泡阶段,则必须将其指定为冒泡阶段(false),否则同样无法卸载!

文章评论

旅行,写作,编程
旅行,写作,编程
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
代码女神横空出世
代码女神横空出世
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
每天工作4小时的程序员
每天工作4小时的程序员
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
我是如何打败拖延症的
我是如何打败拖延症的
编程语言是女人
编程语言是女人
如何成为一名黑客
如何成为一名黑客
程序员和编码员之间的区别
程序员和编码员之间的区别
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
一个程序员的时间管理
一个程序员的时间管理
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序员应该关注的一些事儿
程序员应该关注的一些事儿
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
程序员都该阅读的书
程序员都该阅读的书
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
为什么程序员都是夜猫子
为什么程序员都是夜猫子
我的丈夫是个程序员
我的丈夫是个程序员
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
总结2014中国互联网十大段子
总结2014中国互联网十大段子
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
程序员的鄙视链
程序员的鄙视链
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
 程序员的样子
程序员的样子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
中美印日四国程序员比较
中美印日四国程序员比较
鲜为人知的编程真相
鲜为人知的编程真相
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
程序员必看的十大电影
程序员必看的十大电影
Java程序员必看电影
Java程序员必看电影
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
那些争议最大的编程观点
那些争议最大的编程观点
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有