`

DOM标准与IE的html元素事件模型区别

 
阅读更多

事件

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挂载法
<div onclick ="alert(this.innerHTML);" > </div>

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的事件监听器就不再收到通知,不再被处理。
事件传递后的默认处理是指,通常浏览器在事件传递并处理完后会执行与该事件关联的默认动作(如果存在这样的动作)。例如,如果表单中inputtype 属性是 “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代码作分析:
<div id ="div0" onclick ="alert('current is '+this.id)" >
<div id ="div1" onclick ="alert('current is '+this.id)" >
<div id ="div2" onclick ="alert('current is '+this.id)" >
<div id ="event_source" style ="height: 200px; width: 200px; background-color: red;" onclick ="alert('current is '+this.id)" > </div>
</div>
</div>
</div>

HTML运行后点击红色区域,这是最里层的DIV,根据上面说明,无论是DOM标准还是IE,直接写在html里的监听处理函数是事件冒泡传递时调用的,由最里层一直往上传递,所以会先后出现
current is event_source
current is div2
current is div1
current is div0
current 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_source
current is div2
在支持DOM标准的浏览器中,添加以下代码:
document.body .addEventListener ( 'click' , function ( event) {
event.stopPropagation ( ) ;
} , true ) ;

以上代码中的监听函数由于是捕获型传递时被调用的,所以点击红色区域后,虽然事件源是ID为event_source的元素,但捕获型选传递,从最顶层开始,body结点监听函数先被调用,并且取消了事件进一步向下传递,所以只会出现
current is body

分享到:
评论

相关推荐

    IE6升级到IE9兼容性问题和操作手册

    1. 方框模型溢出内容现与方框相交,不再让方框自动增长适应内容。 9 2. 不再支持某些 CSS 筛选器(如 *HTML、_underscore 和 /**/ 注释)。 11 3. 已解决SELECT 元素不能被div覆盖的问题。 14 第二节:IE7-IE8更新 ...

    ie 开发 调试 工具 三合一 companionjs debugbar(5.2) Internet.Explorer.Developer.Toolbar 天涯浪子

    做前端开发的过程中对JS的调试...-浏览和修改Web页的文档对象模型(DOM). -通过多种技术方式定位、选定Web页上的特定元素. -禁止或激活IE设置. -查看HTML对象的类名、ID,以及类似链接路径、tab顺序、快捷键等细节.

    IE Developer Toolbar

     -浏览和修改Web页的文档对象模型(DOM).  -通过多种技术方式定位、选定Web页上的特定元素.  -禁止或激活IE设置.  -查看HTML对象的类名、ID,以及类似链接路径、tab顺序、快捷键等细节.  -描绘表格...

    javascript脚本化文档

    第17章介绍了用于处理事件(以及实现这些任务的遗留技术和特定于IE的技术)的W3C DOM标准。第18章介绍了和HTML表单元素交互的DOM。第22章介绍了如何脚本化一个HTML文档的标记,以及如何为客户端Web页面添加脚本化的...

    IE Dev Toolbar 中文版

    微软发布了Internet Explorer ...-浏览和修改Web页的文档对象模型(DOM). -通过多种技术方式定位、选定Web页上的特定元素. -禁止或激活IE设置. -查看HTML对象的类名、ID,以及类似链接路径、tab顺序、快捷键等细节

    检测浏览器支持哪些HTML5新特性的方法

    当 浏览器渲染 web 页面的时候,它会构造一个文档对象模型(Document Object Model,DOM)。这是一组用于表现页面上 HTML 元素的对象。每一个元素,例如每一个 ,每一个 ,每一个 &lt;span&gt; 都有不同的 DOM 对象表示。...

    ie_developer_toolbar v1.00.2188.0汉化版

    · 浏览和修改 Web 页面的文档对象模型(DOM); · 通过多种方式定位并选定 Web 页面的特定元素; · 有选择的禁用 IE 设置; · 查看 HTML 对象的 Class/ID 名、链接路径、Tab 顺序、快捷键等页面详细信息; · 对...

    javascript完全学习手册2 源码

    10.3 标准事件模型 10.3.1 事件传播 10.3.2 注册事件处理程序 10.3.3 设置对象的事件处理程序 10.3.4 事件的模块和类型 10.3.5 Event接口和对象 10.4 IE事件模型 10.4.1 IEEvent对象 10.4.2 IE的...

    JavaScript王者归来part.1 总数2

     13.1.1 消息与事件响应   13.1.2 浏览器的事件驱动机制   13.2 基本事件处理   13.2.1 事件和事件类型   13.2.2 事件的绑定   13.2.3 直接调用事件处理函数   13.2.4 事件处理函数的返回值   13.2.5...

    javascript完全学习手册1 源码

    10.3 标准事件模型 273 10.3.1 事件传播 273 10.3.2 注册事件处理程序 274 10.3.3 设置对象的事件处理程序 276 10.3.4 事件的模块和类型 276 10.3.5 Event接口和对象 278 10.4 IE事件模型 280 10.4.1 IE Event对象 ...

    JavaScript基础和实例代码

    3.6 现代事件模型与Event对象 3.7 IE4中的Event对象 3.7.1 对象属性 3.7.2 事件上溯 3.7.3 阻止事件上溯 3.7.4 事件改向 3.8 NN4中的Event对象 3.8.1 对象属性 3.8.2 事件捕获 3.8.3 关闭事件捕获 3.8.4 事件传递 ...

    源文件程序天下JAVASCRIPT实例自学手册

    3.6 现代事件模型与Event对象 3.7 IE4中的Event对象 3.7.1 对象属性 3.7.2 事件上溯 3.7.3 阻止事件上溯 3.7.4 事件改向 3.8 NN4中的Event对象 3.8.1 对象属性 3.8.2 事件捕获 3.8.3 关闭事件捕获 3.8.4 事件传递 ...

    响应式开发HTML重组库Intention.js.zip

    Intention.js和Context.js,Intention.js库主要是用来管理响应轴以及基 于元素规格和事件改变来操纵元素,Context.js是Intention.js的一个实现,在进行响应式设计时提供一组通用的使用模型。 Intention.js有三个...

    IEDevToolBar V1.00.2188.0

    微软发布了Internet Explorer ...-浏览和修改Web页的文档对象模型(DOM). -通过多种技术方式定位、选定Web页上的特定元素. -禁止或激活IE设置. -查看HTML对象的类名、ID,以及类似链接路径、tab顺序、快捷键等细节.

    js实现的点击div区域外隐藏div区域

    首先看下JS的事件模型,JS事件模型为向上冒泡,如onclick事件在某一DOM元素被触发后,事件将跟随节点向上传播,直到有click事件绑定在某一父节点上,如果没有将直至文档的根。 阻止冒泡:1、stopPropagation()对于非...

    XML高级编程pdf

    9.6 XSL转换与DOM转换的比较 9.7 小结 第10章 XML和数据库 10.1 存储XML 10.1.1 持续性问题 10.1.2 文档管理 10.1.3 XML存储和数据库 10.1.4 结论 10.2 XML的交换 10.2.1 数据标准 10.2.2 查询标准 ...

    精通AngularJS part1

    自定义HTML元素与IE的老版本124 47使用过滤器处理模型变换124 内置过滤器125 格式化过滤器125 数组变换过滤器125 编写自定义过滤器——分页示例131 从JavaScript代码中访问过滤器133 过滤器做什么与不做什么...

    XML高级编程 (Extensible Markup Language)

    9.6 XSL转换与DOM转换的比较 9.7 小结 第10章 XML和数据库 10.1 存储XML 10.1.1 持续性问题 10.1.2 文档管理 10.1.3 XML存储和数据库 10.1.4 结论 10.2 XML的交换 10.2.1 数据标准 10.2.2 查询标准 ...

    XML 高级编程(高清版)

    9.6 XSL转换与DOM转换的比较 9.7 小结 第10章 XML和数据库 10.1 存储XML 10.1.1 持续性问题 10.1.2 文档管理 10.1.3 XML存储和数据库 10.1.4 结论 10.2 XML的交换 10.2.1 数据标准 10.2.2 查询标准 ...

Global site tag (gtag.js) - Google Analytics