前些天有人电话里问我dom事件模型,其实这个东西我之前肯定是有看过,好好的理过的。只不过,公司面对的客户群就是纯ie的的客户,所以对标准浏览器的事件模型给忘记了。当时只回答了ie下是冒泡(Bubbling),标准浏览器是捕获(Capture)。
回头去搜了一下,标准浏览器还有一个冒泡(Bubbling)的过程。而Netscape Navigatior才只有捕获。
我们都知道DOM(文档对象模型)是一个树形结构,当一个html元素产生一个事件时,这个事件会在元素节点与根节点之间的路径传播,路径中的节点都会触发这个事件。
DOM事件模型主要有三种模型:冒泡、捕获和标准事件模型。
之前浏览器都是有自己的事件模型,到DOM Level3后,才陆陆续续的支持DOM标准的事件模型,即捕获与冒泡型。这两种事件模型肯定是各有优缺点了,所以标准浏览器的事件模型会采用两者的结合体。现在主流的浏览器firefox,opera,safari都支持标准的DOM事件处理模型,而ie仍使用自己的模型。
<div class="wrapper"> <div class="head"> head </div> <div class="mainbody" > lalsdfjasdk jfklsdajf lkasjdf dsf sdf <br/> lalsdfjasdk jfklsdajf lkasjdf<br/> lalsdfjasdk jfklsdajf lkasjdf<br/> <button class="btn">button</button> </div> </div>这段html代码在IE下事件的传播路径(冒泡)是这样的:
button.btn - > div.mainbody - > div.wrapper - > body - >document
在标准浏览器下事件的传播路径会是这样:
window - > document - > body - > div.wrapper - > div.mainbody - > button.btn
- > div.mainbody - > div.wrapper - > body - >document - > window
javascript使用事件驱动,先给一个元素添加事件监听函数,当这个元素的对应事件对触发后,就会调用添加的事件监听函数。
下面就是javascript中给元素添加事件监听函数的方法:
直接在html元素上添加
<button id="sbtBtn" onclick="btnClick();" class="btn">button</button>用相应的js属性
document.getElementById("sbtBtn").onclick = function(){ //add your code }用注册函数
document.getElementById("sbtBtn").addEventListener("click", function(){ //add your code },true);这三种方法在作用域以及事件传播等都是有区别,而这个区别就是DOM level 0 ,DOM level 2事件模型的区别了。关于这个区别,我在最近的技术支持的过程中有一点体会。这也是我立马来看DOM事件模型的原因了。
** DOM Level 0**
像上面前两种方式,都是这个级别的事件模型了。一般说来,在这个监听函数里返回一个false值,会阻止浏览器默认的执行动作,this指向目标元素。
从技术上来说,W3C的DOM标准并不支持上述最原始的添加事件监听函数的方式,这些都是在DOM标准形成前的事件模型。尽管没有正式的W3C标准,但这种事件模型仍然得到广泛应用,这就是我们通常所说的0级DOM。
DOM 级别 0 不是 W3C 规范。而仅仅是对在 Netscape Navigator 3.0 和 Microsoft Internet Explorer 3.0 中的等价功能性的一种定义。
DOM 发展过程中的关键角色有:ArborText、IBM、Inso EPS、JavaSoft、Microsoft、Netscape、Novell、the Object Management Group、SoftQuad、Sun Microsystems 以及 Texcel。
W3C 的 DOM 级别 1 建立于此功能性之上。 DOM Level 1
DOM级别1于1998年10月1日成为W3C推荐标准。1级DOM标准中并没有定义事件相关的内容,所以没有所谓的1级DOM事件模型。** **
DOM 级别 1 专注于 HTML 和 XML 文档模型。它含有文档导航和处理功能。
DOM 级别 1 于 1998 年 10 月 1 日成为 W3C 推荐标准。
第二版的工作草案在 2000 年 9 月 29 日。 **DOM Level 2 **
如前面所述,标准浏览器分捕获和冒泡两个阶段,前面添加事件监听的第三种方法就是这个级别的实现方式。但是这个方法我们还要详细的去探究这个方法的用法:
addEventListener(eventType,handler,useCapture),有三个参数,其中第三个参数决定了事件的注册函数在哪个事件传播阶段触发,如果为true则在捕获阶段,反之则在冒泡阶段。当一个目标注册了捕获阶段的监听函数,如果其祖先节点也注册了,那么在传播的过程中就会执行这些函数。
在执行监听函数时,会传入一个event对象,其实有一些常用的属性我们会经常用到:
type:
发生事件的类型,如click , mouseover, mouseout等
target:
发生事件的节点可能与currentTarget不同
currentTarget:
正在处理事件的节点,如果在capturing阶段和冒泡阶段处理事件,这个属性就与target属性不同。在事件监听函数中应该用这个属性而不是this
stopPropagation():
可以阻止事件从当前正在处理他的节点传播
preventDefault():
阻止浏览器执行与事件相关的默认动作,与0级DOM中返回false一样
clientX, clientY:
鼠标相对于浏览器的x坐标y坐标
screenX, screenY:
鼠标相对于显示器左上角的x坐标y坐标
IE下的处理方式
IE下没有addEventListener,但是有自己类似的方法:attachEvent,这个方法只有两个参数,第一个参数为事件类型的前面需要加"on",由于 ie下没有捕获,所以没有类似标准浏览器的第三个参数。
IE上可以对元素进行多次同样的绑定,标准浏览器只会绑定一次。ie下event对象不是事件处理程序传入的参数,而是全局的变量:window.event,例如中断冒泡用window.event.cancelBubble = true.
event常用属性
type: 兼容DOM的type属性
srcElement:
兼容DOM的target属性
clientX, clientY:
兼容DOM的clientX, clientY属性
cancelBubble:
布尔值,设为true同调用stopPropagation()
returnValue:
布尔值,设为false同调用preventDefault()
卸载方法
Object.removeEventListener(eventType,handler,useCapture);//DOM标准的事件卸载方式 Object.detachEvent(eventType,handler);//IE内核的事件卸载方式
关于事件类型,各大浏览器支持的情况:Event compatibility tables
参考 :
2、《JavaScript高级程序设计(第2版)》