




已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
DOM 事件模型 事件HTML元素事件是浏览器内在自动产生的,当有事件发生时html元素会向外界(这里主要指元素事件的订阅者)发出各种事件,如click,onmouseover,onmouseout等等。DOM事件流DOM(文档对象模型)结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素结点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流。主流浏览器的事件模型早在2004前在HTML元素事件的订阅,发送,传播,处理模型上各浏览器实现并不一致,直到DOM Level3中规定后,多数主流浏览器才陆陆续续支持DOM标准的事件处理模型 捕获型与冒泡型。目前除IE浏览器外,其它主流的Firefox, Opera, Safari都支持标准的DOM事件处理模型。IE仍然使用自己的模型,即冒泡型,它模型的一部份被DOM采用,这点对于开发者来说也是有好处的,只使用DOM标准,IE都共有的事件处理方式才能有效的跨浏览器。冒泡型事件(Bubbling)这是IE浏览器对事件模型的实现,也是最容易理解的,至少笔者觉得比较符合实际的。冒泡,顾名思义,事件像个水中的气泡一样一直往上冒,直到顶端。从DOM树型结构上理解,就是事件由叶子结点沿祖先结点一直向上传递直到根结点;从浏览器界面视图HTML元素排列层次上理解就是事件由具有从属关系的最确定的目标元素一直传递到最不确定的目标元素.捕获型事件(Capturing)Netscape Navigator的实现,它与冒泡型刚好相反,由DOM树最顶层元素一直到最精确的元素,这个事件模型对于开发者来说(至少是我.)有点费解,因为直观上的理解应该如同冒泡型,事件传递应该由最确定的元素,即事件产生元素开始。但这个模型在某些情况下也是很有用的,接下来会讲解到。DOM标准事件模型因为两个不同的模型都有其优点和解释,DOM标准支持捕获型与冒泡型,可以说是它们两者的结合体。它可以在一个DOM元素上绑定多个事件处理器,并且在处理函数内部,this关键字仍然指向被绑定的DOM元素,另外处理函数参数列表的第一个位置传递事件event对象。首先是捕获式传递事件,接着是冒泡式传递,所以,如果一个处理函数既注册了捕获型事件的监听,又注册冒泡型事件监听,那么在DOM事件模型中它就会被调用两次。注册与移除事件监听器注册事件监听器,或又称订阅事件,当元素事件发生时浏览器回调该监听函数执行事件处理。目前主流浏览器中有两种注册事件的方法,一种是IE浏览器的,另一种是DOM标准的。1.直接JS或HTML挂载法 element.onclick = function()alert(this.innerHTML);移除时将事件属性设为nul即可,这个也是最常用的方法了,优缺点也是显然的: 简单方便,在HTML中直接书写处理函数的代码块,在JS中给元素对应事件属性赋值即可 IE与DOM标准都支持的一种方法,它在IE与DOM标准中都是在事件冒泡过程中被调用的。 可以在处理函数块内直接用this引用注册事件的元素 要给元素注册多个监听器,就不能用这方法了2. IE下注册多个事件监听器与移除监听器方法IE浏览器中HTML元素有个attachEvent方法允许外界注册该元素多个事件监听器,例如 element.attachEvent(onclick, observer);attachEvent接受两个参数。第一个参数是事件名称,第二个参数observer是回调处理函数。这里得说明一下,有个经常会出错的地方,IE下利用attachEvent注册的处理函数调用时this指向不再是先前注册事件的元素,这时的this为window对象了,笔者很奇怪IE为什么要这么做,完全看不出好处所在。要移除先前注册的事件的监听器,调用element的detachEvent方法即可,参数相同。 element.detachEvent(onclick, observer);3. DOM标准下注册多个事件监听器与移除监听器方法实现DOM标准的浏览器与IE浏览器中注册元素事件监听器方式有所不同,它通过元素的addEventListener方法注册,该方法既支持注册冒泡型事件处理,又支持捕获型事件处理。 element.addEventListener(click, observer, useCapture);addEventListener方法接受三个参数。第一个参数是事件名称,值得注意的是,这里事件名称与IE的不同,事件名称是没on开头的;第二个参数observer是回调处理函数;第三个参数注明该处理回调函数是在事件传递过程中的捕获阶段被调用还是冒泡阶段被调用移除已注册的事件监听器调用element的removeEventListener即可,参数不变. element.removeEventListener(click, observer, useCapture);跨浏览器的注册与移除元素事件监听器方案弄清楚DOM标准与IE的注册元素事件监听器之间的异同后,就可以实现一个跨浏览器的注册与移除元素事件监听器方案: /注册function addEventHandler(element, evtName, callback, useCapture) /DOM标准if (element.addEventListener) element.addEventListener(evtName, callback, useCapture); else /IE方式,忽略useCapture参数element.attachEvent(on + evtName, callback);/移除/注册function removeEventHandler(element, evtName, callback, useCapture) /DOM标准if (element.removeEventListener) element.removeEventListener(evtName, callback, useCapture); else /IE方式,忽略useCapture参数element.dettachEvent(on + evtName, callback);如何取消浏览器事件的传递与事件传递后浏览器的默认处理先说明取消事件传递与浏览器事件传递后的默认处理是两个不同的概念,可能很多同学朋友分不清,或者根本不存在这两个概念。取消事件传递是指,停止捕获型事件或冒泡型事件的进一步传递。例如上图中的冒泡型事件传递中,在body处理停止事件传递后,位于上层的document的事件监听器就不再收到通知,不再被处理。事件传递后的默认处理是指,通常浏览器在事件传递并处理完后会执行与该事件关联的默认动作(如果存在这样的动作)。例如,如果表单中input type 属性是 “submit”,点击后在事件传播完浏览器就就自动提交表单。又例如,input 元素的 keydown 事件发生并处理后,浏览器默认会将用户键入的字符自动追加到 input 元素的值中。要取消浏览器的件传递,IE与DOM标准又有所不同。在IE下,通过设置event对象的cancelBubble为true即可。 function someHandle() window.event.cancelBubble = true;DOM标准通过调用event对象的stopPropagation()方法即可。 function someHandle(event) event.stopPropagation();因些,跨浏览器的停止事件传递的方法是: function someHandle(event) event = event | window.event;if(event.stopPropagation)event.stopPropagation();else event.cancelBubble = true;取消事件传递后的默认处理,IE与DOM标准又不所不同。在IE下,通过设置event对象的returnValue为false即可。 function someHandle() window.event.returnValue = false;DOM标准通过调用event对象的preventDefault()方法即可。 function someHandle(event) event.preventDefault();因些,跨浏览器的取消事件传递后的默认处理方法是: function someHandle(event) event = event | window.event;if(event.preventDefault)event.preventDefault();else event.returnValue = false;捕获型事件模型与冒泡型事件模型的应用场合标准事件模型为我们提供了两种方案,可能很多朋友分不清这两种不同模型有啥好处,为什么不只采取一种模型。这里抛开IE浏览器讨论(IE只有一种,没法选择)什么情况下适合哪种事件模型。1. 捕获型应用场合捕获型事件传递由最不精确的祖先元素一直到最精确的事件源元素,传递方式与操作系统中的全局快捷键与应用程序快捷键相似。当一个系统组合键发生时,如果注册了系统全局快捷键监听器,该事件就先被操作系统层捕获,全局监听器就先于应用程序快捷键监听器得到通知,也就是全局的先获得控制权,它有权阻止事件的进一步传递。所以捕获型事件模型适用于作全局范围内的监听,这里的全局是相对的全局,相对于某个顶层结点与该结点所有子孙结点形成的集合范围。例如你想作全局的点击事件监听,相对于document结点与document下所有的子结点,在某个条件下要求所有的子结点点击无效,这种情况下冒泡模型就解决不了了,而捕获型却非常适合,可以在最顶层结点添加捕获型事件监听器,伪码如下: function globalClickListener(event) if(canEventPass = false) /取消事件进一步向子结点传递和冒泡传递event.stopPropagation();/取消浏览器事件后的默认执行event.preventDefault();这样一来,当canEventPass条件为假时,document下所有的子结点click注册事件都不会被浏览器处理。2. 冒泡型的应用场合可以说我们平时用的都是冒泡事件模型,因为IE只支持这模型。这里还是说说,在恰当利用该模型可以提高脚本性能。在元素一些频繁触发的事件中,如onmousemove, onmouseover,onmouseout,如果明确事件处理后没必要进一步传递,那么就可以大胆的取消它。此外,对于子结点事件监听器的处理会对父层监听器处理造成负面影响的,也应该在子结点监听器中禁止事件进一步向上传递以消除影响。综合案例分析最后结合下面HTML代码作分析:HTML运行后点击红色区域,这是最里层的DIV,根据上面说明,无论是DOM标准还是IE,直接写在html里的监听处理函数是事件冒泡传递时调用的,由最里层一直往上传递,所以会先后出现current is event_sourcecurrent is div2current is div1current is div0current is body添加以下片段: var div2 = document.getElementById(div2);addEventHandler(div2, click, function(event)event = event | window.event;if(event.stopPropagation)event.stopPropagation();else event.cancelBubble = true;, false);当点击红色区域后,根据上面说明,在泡冒泡处理期间,事件传递到div2后被停止传递了,所以div2上层的元素收不到通知,所以会先后出现:current is event_sourcecurrent is div2在支持DOM标准的浏览器中,添加以下代码: document.body.addEventListener(click, function(event)event.stopPropagation();, true);以上代码中的监听函数由于是捕获型传递时被调用的,所以点击红色区域后,虽然事件源是ID为event_source的元素,但捕获型选传递,从最顶层开始,body结点监听函数先被调用,并且取消了事件进一步向下传递,所以只会出现current is body关于DOM事件模型的两件事多图日期:2007年11月26日 作者: o 事件捕捉(Event Capture)的实现问题 o IE的高级事件处理模型的问题 一、事件捕捉(Event Capture)的实现问题 首先在说这件事前,先感谢一下Realazy。 W3C DOM Level2的事件模型规范中,事件在DOM树中的传播过程(从根节点到目标节点)被分为了两个阶段:捕捉(Capture)和冒泡(Bubbling)。下面这个图能大概的说明整个过程:关于DOM事件模型的两件事多图日期:2007年11月26日 作者: The DOM spec states that capturing events should not fire on target, because the idea of a capturing event is to detect events before they reach their targets. Because of bugs in Gecko and Safari, web content that is tested mostly with Firefox or other Gecko-based browsers sometimes expects capturing listeners to fire on target. Such content will fail in Opera 7, 8 and current releases of 9 because of its correct implementation of the standard. 大意是说:DOM规范中陈述了捕捉型的事件不应该在目标元素上被执行,因为捕捉型事件的用意就是为了监测到达目标元素之前的事件。Firefox和Safari的实现都是带有bug的。 再来看看W3C的DOM Events规范中的原话:A capturing EventListener will not be triggered by events dispatched directly to the EventTarget upon which it is registered. 所以,在整个事件传播中,被执行的顺序是: 1. 父元素中所有的捕捉型事件(如果有)自上而下地执行 2. 目标元素的冒泡型事件(如果有) 3. 父元素中所有的冒泡型事件(如果有)自下而上地执行 在了解了这些后,也许还是不要使用事件捕捉为妙,至少暂时不要。 二、IE的高级事件处理模型的问题 重复绑定 IE下没有addEventListener,但是也有自己的attachEvent,即所谓的Microsoft Model。二者的实现基本相同只是attachEvent的第一个参数(事件类型)需要加”on”,而addEventListener不用,另外attachEvent因为不支持事件捕捉,所以也没有第三个参数。 然而,attachEvent还有一个很要命的问题:重复绑定事件。(这是从ppk on JavaScript中学到的) 一个例子: function sayHello()alert(Hello, world!);/ W3C Model$(div1).addEventListener(click, sayHello, false); (from W3C) 如果想创建一个捕捉事件,在支持W3C 事件模型的浏览器中,将addEventListener的第三个参数设为true就好了。例如: document.getElementById(foo).addEventListener(click,function()alert(Hello, world!);,true); 前一阵因为想弄懂事件捕捉,所以做了点小实验,分别在Firefox 2、Safari 3 on Windows和Opera 9上实践了事件捕捉(当然,因为IE不支持事件捕捉,所以),实验的原理见下图: ID为div1和div2的两个元素都被委派了捕捉阶段的事件处理函数,这样: o 当点击#div1(蓝色区域)时,应该会alert出”div1 o 当点击#div2(黄色区域)时,应该会先alert出”div1,再alert出”div2,因为在事件捕捉阶段,事件是从根元素向下传播的,#div1是#div2的父元素,自然绑定在#div1上的
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 网络通信java面试题及答案
- 消化内科面试题库及答案
- 2026届陕西省渭南市潼关县高一化学第一学期期末质量检测试题含解析
- 大专阿语考试题及答案
- 校车安全操作培训内容
- 浙江初会考试试题及答案
- 家电公司拓展训练组织规定
- 2026届山东省昌邑市文山中学化学高二第一学期期末学业水平测试试题含答案
- 保安理论知识培训总结课件
- 保安理论培训知识课件
- 2025-2030潜伏性结核感染(LTBI)测试行业市场现状供需分析及投资评估规划分析研究报告
- 县级医院运营管理制度
- XX学校(幼儿园)食堂管理各岗位廉政(廉洁)风险点及防控措施一览表
- 钢结构钢爬梯包工包料合同范本
- 2025届高考数学二轮复习专题21排列组合与概率必刷小题100题教师版
- 家庭房屋财产协议书
- 股东决策协议书模板
- 2025年家畜饲养员及繁殖学职业技能资格知识考试题与答案
- NB/T 11525-2024气动、电动调度单轨吊车技术条件
- 中华人民共和国民营经济促进法
- 2025年全国特种设备观光车N1证理论考试笔试试题(含答案)
评论
0/150
提交评论