事件就是用户或者浏览器自身执行的某种动作。诸如click、load、和scroll等等,都是事件的名字。而响应某个事件的函就叫做事件处理程序(或事件侦听器)。事件处理程序的名字都是以”on“开头,因此ckick事件的事件处理程序就是onclick,load的事件处理程序就是onload。 页面中添加事件的有几种方式- 直接将代码写在HTMl上
<div onclick="alert('Hello World');">Nowamagic</div> 代码少的还勉强可以,代码多的话就哭了写页面的哥们了。 - 定义一个函数,分配给html元素
<script type="text/javascript"> function clk(){} </script> //..... <div onclick="clk()">Div2 Element</div> 这样做虽然能减少html代码上的js量,但是这样子做有几个缺点:用户可能在HTMl代码已经出现在页面上,但是js事件函数可能还没加载进来的情况下就点击了事件对象元素,从而导致错误;还有就是HTML与javascript代码还是未分离完全,如果要修改就要改HTML代码和javascript代码两处 - HTML与javascript代码完全分离
document.getElementById('myButton').onclick = function(){ alert('Hello!'); } <div id="myButton">点击按钮/div> 它只需要HTML元素提供一个id属性(或其它能获取该元素对象的方式),就可以实现事件的注册。真正做到HTML与javascript代码完全分离,结构与行为完全分离的事件处理方法。
如何监听事件DOM Leavl 0DOM Leavl 0是最早的事件处理形式,它既可以直接写在HTMl上,也可以把一个函数分配给一个事件处理程序。然而,这种方式给一个元素的同一事件只允许一个处理器。因此,我们还要继续完善。 W3C DOM Leavl 2 – 事件监听器通过W3C DEMO Leavl 2事件处理,我们不会直接把一个函数分配给一个事件处理程序;相反,我们将新函数添加一个事件监听器: var el = document.getElementById('myButton') el.addEventListener( 'click', function(){ alert('Hello!'); }, false) 尽管这个方法看起来比之前那个方法复杂了一点,但是那些额外的代码还是有必要打出来的。对于DOM级别2的事件最大的好处就是一个事件可以注册许多处理器。 addEventlistener的头两个参数是目标对象和事件,不仅如此,函数最后一个参数,可以指定处理器是在捕获阶段还是冒泡阶段被触发(通过设置”addEventListener()”函数的第三个参数来指定 – true表示在捕获阶段,false表示在冒泡阶段) 接下来将针对W3C DOM Leavl 2事件进行讨论。 事件在文档中被传递的两种模型W3C DOM Leavl 2事件流包括三个阶段:事件捕获阶段、处于目标简短和事件冒泡阶段。 首先我们了解下事件冒泡和事件捕获。 事件冒泡在页面上有多个事件,也可以多个元素响应同一个事件。假设网页上有两个元素,其中一个元素嵌套在另一个元素中,并且都被绑定了 click 事件,同时 body 也绑定了 click 事件,如下: 很明显,每个元素都会按照(inside→outside)的冒泡型事件,所以事件冒泡会引起预料之外的效果。事件冒泡是IE-DOM处理事件对象的方法。 事件捕获事件捕获和事件冒泡是刚好相反的两个过程,事件捕获是按照(outside→inside)的冒泡型事件开始触发。因此拿以上冒泡例子,alert信息是跟事件冒泡完全相反的顺序。 一些注意事项: - W3C DOM Leavl 2标准的addEventListener方法执行事件的顺序是按照事件注册的顺序执行的。而IE的attachEvent方法则相反–后注册的事件先觖发,先注册的事件后触发。
- W3C DOM Leavl 2标准的浏览器文本节点也会冒泡,而IE内核的浏览器文本节点不会冒泡。
- W3C DOM Leavl 2浏览器事件对象与IE内核的浏览器事件不同(具体请参阅)。
- DOM标准的浏览器事件卸载方式与IE内核的事件卸载方式不同。
接下来我们就来解决跨浏览器的事件处理的方案。 跨浏览器的事件处理函数前面我们介绍了事件冒泡和事件捕获两种事件事件获取方式,而W3C模型 是两者中和。就是事件发生时,先从顶层开始进行事件捕获,直到事件触发到达了事件源元素。然后,再从事件源往上进行事件冒泡,直到到达document。 利用W3C DOM Leavl 2事件监听器,就是 addEventListener函数。我们可以自己选择绑定事件时采用事件捕获还是事件冒泡,方法就是绑定事件时通过addEventListener函数,上面我们介绍过它的三个参数了:如果第三个参数若是true,则表示采用事件捕获,若是false,则表示采用事件冒泡。 但是在一个支持W3C DOM的浏览器中,按照DOM Leavl 1绑定事件方式,采用的全都是事件冒泡方式。大多数时候,我们也是希望事件从内部嵌套的的元素冒泡到外围元素。 解决方案以上我们介绍过 W3C DOM Leaval 2事件绑定中的addEventlistener,可以为元素添加多个事件,而且最后一个参数还支持事件冒泡或捕获,IE6/7/8仍然没有遵循标准而使用了自己专有的attachEvent,且不支持事件捕获,所有事件都是发生在冒泡阶段。 所以创建一个可重用。实现了DOM Leavl 2事件处理的事件处理函数,但是,它还是要跨浏览器。如下经典代码 此处理函数接受3个函数:目标对象、事件(作为一个字符串),以及函数名称。首先测试对象,看看它是否支持addEventListener(W3C DOM Leaval 2的事件监听方法),如果支持这个方法,就把事件映射到事件处理函数。回到代码,因为IE6、7、8不支持addEventListener,所以检查是否支持attachEvent,记得前面加”on“,因为不加”on“只是事件的名字,但是因为IE6、7、8只支持向上冒泡,所以此方案中 addEventListener的第三个参数是false。最后为了兼容DOM leaval 0事件处理,还要加最后一行代码。 使用W3C DOM Leavl 2处理事件事件监听不会有覆盖之前绑定事件的现象,每个绑定的事件都会被执行,不过 attachEvent 为元素增加的一系列事件不是以添加它们顺序执行的,而是以相反的顺序触发。最重要的是,采用事件监听给对象绑定方法后,可以解除相应的绑定。跟以上代码类似,removeEventListener跟addEventListener对应,detachEvent跟eventType对应,得到如下解决方案: 在DOM标准的事件卸载方式中需要注意的是:事件捕获的参数。如果你的事件是注册在捕获阶段,则卸载事件时,必须将其指定为捕获阶段(true),否则无法卸载;如果你的事件注册在注册在冒泡阶段,则必须将其指定为冒泡阶段(false),否则同样无法卸载。 现在,如果我们想停止监听一个事件,可以直接调用stopListening,同样传入3个参数:目标对象、事件和事件处理函数。 阻止冒泡因为大部分浏览器都是按照DOM Leavl 1绑定事件方式,采用的全都是事件冒泡方式。所以阻止事件冒泡(嵌套元素中传播)是很有必要的。如下方案: 因为IE8、7、6不支持W3C DOM Leavel 2不支持,那么我们就设置event.cancelBubble 的属性值为 true;而支持其他现代浏览器则使用W3C DOM Leavel 2的,则调用stopPropagation方法。 最后罗列文章中出现的几个Event方法 - W3C DOM Leavl 2绑定和解除事件的方法:addEventListener和removeEventListener:
- IE绑定和解除事件的方法:attachEvent和detachEvent
- 取消事件:W3C DOM Leavl 2使用preventDefault(),iE直接返回false
- 阻止事件在嵌套函数中传播(阻止冒泡和捕获):W3C DOM Leavl 2使用stopPropagation(),IE中cancelBubble返回true
本文出现所有DEMO下载:js-attachEvent.rar
|