`
sunzhyng
  • 浏览: 59114 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

同时支持三种事件模型

阅读更多
?

事件使得客户端的 JavaScript 有机会被激活,并得以运行。在一个 Web 页面装载之后,运行脚本的唯一方式,就是响应系统或者用户的动作。虽然从第一个支持脚本编程的浏览器面世以来,简单的事件被实现为 JavaScript 的一部分;但是大多数最近出现的浏览器都实现了强壮的事件模型,使脚本可以更加智能地处理事件。现在的问题在于:为了支持各种浏览器,您必须和多个先进的事件模型做斗争,准确地说,是三个。

这三个事件模型分别和下面的文档对象模型(Document Object Model,即 DOM)三巨头结盟:Netscape Navigator 4 (NN4),Macintosh 和 Windows 系统的 Internet Explorer 4 及其更新版本(IE4+),以及在 Safari 中得到实现的 W3C DOM。尽管这些模型之间有些地方存在一些本质的差别,但是在一些简易的 JavaScript 的帮助下,它们都可以同时适用于同一个文档。本文主要着眼于相互冲突的事件模型中的两个关键方面:

  • 把一个事件和 HTML 元素绑定起来的方法。
  • 在事件被触发后如何对之进行处理。

事件绑定的方法

事件绑定是指构造一个响应系统或者用户动作的 HTML 元素的过程。在不同的浏览器版本中,有不少于五种事件绑定技术。下面我们快速地介绍一下这些技术。

事件绑定方法I:绑定元素属性

最简单和向后兼容性最好的事件绑定方法是把事件绑定到元素标识的属性。事件属性名称由事件类型外加一个“on”前缀构成。尽管HTML属性并不是大小写敏感的,人们还是定义了一个规则,规定事件类型的每一个“词”的首字母大写,比如 onClickonMouseOver 。这些属性也被称为事件处理器 ,因为它们指示了元素如何“处理”特定的事件类型。

正确的事件处理器属性的值在形式上是被引号包含的 JavaScript 语句。最常见的值是一条调用某个脚本函数的语句,而被调用的函数在位于文档前部的 <script> 标识中定义--该标识通常位于 <HEAD> 部分。举例来说,下面的函数:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">function myFunc() { // script statements here }</SPAN> </pre> <p CLASS="WF"> 可以被定义为一个按键控件的事件处理器,按键的定义如下:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF"><INPUT TYPE="button" NAME="myButton" VALUE="Click Here" onClick="myFunc()"></SPAN> </pre> <p CLASS="WF"> 把事件绑定到元素属性上有一个优点,即可以支持开发者把参数传递给事件处理器函数。接收事件的元素的引用则由一个特殊的参数值--<code>this</CODE> 关键字来传递。下面的代码演示一个函数如何借助传入参数,把任意数目的文本框的内容转化为大写:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF"><SCRIPT LANGUAGE="JavaScript"> function convertToUpper(textbox) { textbox.value = textbox.value.toUpperCase(); } </script> ...

事件绑定方法II:绑定对象属性

对于 NN3+ 和 IE4+ 这两类浏览器,脚本编程人员可以以脚本语句的方式把事件绑定到对象上,而不是绑定到元素标识的属性上。每一个负责事件响应的元素对象都为自己能够识别的事件设置了相应的属性。对象属性名称是元素标识属性的小写形式,比如 onmouseover 。NN4 还接受 interCap(即首字小写,之后的每一个词的首字大写)版本的属性名,但是考虑到跨浏览器的兼容性,所有字母都是小写的名称会更安全一些。

当您把一个函数的引用赋值给一个事件属性的时候,就发生了绑定。函数的引用是指函数的名称,但是不带函数定义中的括号。因此,如果要为一个名为 myButton 的按键的点击事件(click)进行绑定,使之激活一个定义为 myFunc() 的函数,则其赋值语句如下所示:

document.forms[0].myButton.onclick = myFunc;


您应该注意一点:在事件触发的时候,没有办法向事件函数传递参数。本文在稍候对事件处理过程的讨论中还会回顾这个问题。

事件绑定方法III: 绑定 IE4+ <script> 标识</FONT></H2> <p CLASS="WF">在 IE4+ 中,Microsoft 对 <SCRIPT> 标识实现了自己的扩展,可以将它包含的脚本语句和某个元素的一个事件类型进行绑定。支持这个绑定的标识属性(还没有被 W3C 批准为 HTML 的一部分)是 <code>FOR</CODE> 和 <code>EVENT</CODE>。</P> <p CLASS="WF"><code>FOR</CODE> 属性的值必须是您为元素的 ID 属性分配的唯一标识符。然后,您必须把事件的名称(onmouseover,onclick,等等)分配给 <code>EVENT</CODE> 属性。在上面的按键实例的基础上,我们必须对按键标识进行修改,使之包含一个 <code>ID</CODE> 属性:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF"><INPUT TYPE="button" NAME="myButton" ID="button1" VALUE="Click Here"></SPAN> </pre> <p CLASS="WF">脚本语句并不在函数中,而是在 <SCRIPT> 标识中,如下所示:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF"><SCRIPT FOR="button1" EVENT="onclick"> // script statements here </script>

当然,标识中的语句可以调用页面上其它地方定义的任何函数(或者从.js文件中导入的函数)。然而,这种绑定方式意味着您必须为每一个元素和每一个事件创建一个 <script> 标识。</P> <p CLASS="WF">您还必须小心,只能把这种绑定方法部署在仅供 IE4+ 浏览器浏览的页面。其它任何支持脚本编程而又没有实现这个特殊的 <SCRIPT> 标识的浏览器(包括 IE3),都将把它作为常规的 <SCRIPT> 标识来处理,并试图在页面装载的时候执行这些脚本语句--这不可避免地引起脚本错误。</P> <h2 CLASS="WF"><font SIZE="4">事件绑定方法IV:使用 IE5/Windows 的 attachEvent() 方法</FONT></H2> <p CLASS="WF">早在 W3C DOM 工作组磨砺出标准的事件模型之前,<code>attachEvent()</CODE> 方法已经被实现了,并且可被用于 Windows 版的 IE5 或更新版本的浏览器上的每一个 HTML 元素。</P> <p CLASS="WF"><code>attachEvent()</CODE> 方法的用法如下所示:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF"><i>elemObject</i>.attachEvent("<i>eventName</i>", <i>functionReference</i>);</SPAN> </pre> <p CLASS="WF"><i>eventName</i> 参数的值是表示事件名称的字符串,比如 <code>onmousedown</CODE>。<i>functionReference</i> 参数是一个不带括号的函数引用,和早些时候描述的事件属性方法中一样。因此对于上面例子的按键对象,可以通过如下的脚本语句把函数绑定到按键的 click 事件:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">document.getElementById("button1").attachEvent("onclick", myFunc);</SPAN> </pre> <p CLASS="WF">由于 <code>attachEvent()</CODE> 方法必须严格工作在 IE5+/Windows 的环境中,所以您既可以使用 W3C DOM 的元素引用方式(如上文所示),也可以使用 IE4+ 的引用方式:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">document.all.button1.attachEvent("onclick", myFunc);</SPAN> </pre> <p CLASS="WF"> 这个方法有一个值得注意的地方:您不能在元素被载入浏览器之前执行这个语句。该对象的引用在相应的 HTML 按键元素被浏览器创建之前,都是无效的。因此,要让这样的绑定语句或者在页面的底部运行,或者在 BODY 元素的 <code>onLoad</CODE> 事件处理器调用的函数中运行。</P> <h2 CLASS="WF"><font SIZE="4">事件绑定方法V:使用 W3C DOM 的 addEventListener() 方法</FONT></H2> <p CLASS="WF">Safari 使用的是 W3C DOM 级别2定义的事件绑定机制,这个机制和 IE5/Windows 的 <code>attachEvent()</CODE> 方法很类似,但是有自己的语法。W3C DOM 规范为 DOM 层次中的每一个结点都定义了一个 <code>addEventListener()</CODE> 方法。HTML 元素是 DOM 结点中的一类,在一对元素标识内部的文本结点也是一个结点,也能够接收事件。这一点在 NN6 事件处理过程中经常得到体现,在本文的后面部分您将会看到。</P> <p CLASS="WF"><code>addEventListener()</CODE> 方法的语法如下所示:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF"><i>nodeReference</i>.addEventListener("<i>eventType</i>", <i>listenerReference</i>, <i>captureFlag</i>);</SPAN> </pre> <p CLASS="WF">用 W3C DOM 规范中的行话来说,<code>addEventListener()</CODE> 方法为指定的结点注册了一个事件,表示该结点希望处理相应的事件。这个方法的第一个参数是一个声明事件类型的字符串(不带"on"前缀),比如 <code>click</CODE>,<code>mousedown</CODE>,和 <code>keypress</CODE>。<code>addEventListener()</CODE> 方法的第二个参数可以和早些时候描述过的函数引用同样对待。第三个参数则是一个 Boolean 值,指明该结点是否以DOM中所谓的<i>捕捉模式</i>来侦听事件。事件的捕捉和派发---综合起来称为<i>事件的传播</i>--最后由另一篇文章来描述。对于一个典型的事件侦听器来说,第三个参数应该为 <code>false(假)</CODE>。</P> <h2 CLASS="WF"><font SIZE="4">那种绑定方法最好?</FONT></H2> <p CLASS="WF"> 如果您足够幸运,只需要为某一个操作系统上特定版本的浏览器创建应用程序,则可以为选定的浏览器选择最现代的绑定方式。但是对于跨浏览器的网站作者来说,选择绑定方法则需要面对实质性的挑战。</P> <p CLASS="WF">如果您只计划支持 IE5/Mac,则可以不考虑 <code>attachEvent()</CODE> 和 <code>addEventListener()</CODE> 方法,因为 IE5/Mac 对这两种方法都不支持。这种情况下,比较实际的选择有两种,要么绑定标识属性,要么绑定对象属性。这时就需要费心思了。</P> <p CLASS="WF">一方面,W3C DOM Level 2 承认基于标识属性的方法,并将它推荐为 <code>addEventListener()</CODE> 方法的可接受代替方法。为了和数以百万计的脚本相兼容,所有支持脚本编程的浏览器都支持基于标识属性的事件绑定方法。一些自动化的页面制作工具,比如 DreamWeaver,也把事件处理器的属性嵌入到 HTML 标识中。</P> <p CLASS="WF"> 但是另一方面,在元素标识文件中嵌入面向脚本的信息,又不能将内容从风格及行为中分离开来,这和当前的流行趋势相违背。把事件绑定到对象属性上的方法听起来方向是对的,但是在 W3C 关于 HTML,XHTML,或者 DOM 的标准中,并没有对事件属性提供“官方”的支持。尽管如此,在实际生活中,除了第一代支持脚本编程的浏览器之外,其它浏览器都支持这种方法。</P> <p CLASS="WF"> 一个纯标准论者会认为上述的两种方法都有缺点,但是对于讲究实际的开发者来说,即使考虑到未来主流浏览器的兼容性,这两种方法都是“安全”的。</P> <h2 CLASS="WF"><font SIZE="4">事件的信息矿:事件对象</FONT></H2> <p CLASS="WF"> 所有这三种事件模型的核心都是一个事件对象--它是一个抽象的实体,其属性中包含很多对事件处理函数具有潜在价值的信息。从本文早些时候对事件绑定技术的讨论中,您可能可以推断出事件对象对脚本之所以至关重要,原因之一是除了基于标识属性的绑定方法以外,其它绑定方法都不支持将参数传递到事件处理函数中。</P> <p CLASS="WF"> 事件对象通过提供足够的“挂钩”,使事件处理函数可以读取事件的特征,从而填补了这个缝隙。因此,事件处理函数可以得到接收事件的元素的引用,以及其它一些有用的信息,比如鼠标动作的坐标,鼠标使用的按键,键盘上被按压的键,以及在事件发生的过程中是否有修饰键被按下(比如检测 Shift-click 事件)。</P> <h2 CLASS="WF"><font SIZE="4">访问事件对象</FONT></H2> <p CLASS="WF">虽然事件对象的精确构成因为本文讨论的三种 DOM(NN4,IE4+,以及 W3C/Safari)的不同而有所变化,但是,一个事件处理函数只能通过以下两种方式之一来访问事件对象:NN 方式和 IE 方式。W3C/Safari DOM 事件对象公布给脚本的接口方式和 NN4 的事件对象一样;而 IE4+ 则有自己的方法。</P> <p CLASS="WF">IE4+ 的事件对象更加易于描述,因此我们首先对它进行讨论。简单地说,事件对象是 <code>window</CODE> 对象的一个属性。这意味着在所有的实例中只有一个事件对象。举例来说,在键盘上简单地按压和松开一个按键,会产生三个事件:<code>onKeyDown</CODE>,<code>onKeyPress</CODE>,和 <code>onKeyUp</CODE>(事件的发生顺序和这里的列举顺序相同)。如果 <code>onKeyDown</CODE>事 件激活的函数花费很长的时间进行处理,则浏览器就会把其它两个事件保持在队列中,直到 <code>onMouseDown</CODE> 事件处理完成为止。</P> <p CLASS="WF">而对于 NN4 和 W3C DOM 来说,事件对象看起来就更加抽象一些。除了基于标识属性风格的绑定方法之外,其它绑定方法都是把事件对象自动传递给与事件相绑定的函数。传递给函数的是一个单一的参数。开发者需要在函数中定义一个参数变量,来“接收”该参数的值。为了避免和IE中的 <code>window.event</CODE> 对象互相冲突,请不要把参数命名为 event。举例来说,把它命名为 <code>evt</CODE> 就相当好,相应的事件函数的定义大致如下:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">function myFunc(evt) { // script statements here }</SPAN> </pre> <p CLASS="WF"> 然而,如果您使用的是基于标识属性的事件绑定技术,就必须显式地把事件作为一个参数传递到您调用的函数。为了完成事件的传递,需要把 <code>event</CODE> 这个关键字作为参数进行传递:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">onClick = "myFunc(event)"</SPAN> </pre> <p CLASS="WF">外部传入的参数是您的事件处理函数和 NN 的事件对象之间的唯一联系纽带。如果在主事件处理函数内部调用的其它函数需要该对象或者该对象的属性值,则您可以把该对象或其属性值作为参数中继给这些函数。</P> <p CLASS="WF">如果您想知道 IE 是否把事件的引用保存在 <code>window.event</CODE> 属性中,那答案是“是”。使用这个语法交集是相当安全的,因为在 NN 和 IE 这两个浏览器,被传递到事件处理函数的事件对象都有您所期望的当前事件的属性值。</P> <h2 CLASS="WF"><font SIZE="4">兼容两种事件对象引用</FONT></H2> <p CLASS="WF"> 设想在处理事件时,我们需要在一个事件函数中考察一个或者多个事件属性。这是一个简单的技术,可以使事件处理函数和作为参数传入的事件对象协同工作,或者从 <code>window.event</CODE> 属性中读取信息。而且,这个技术不必处理不同的浏览器版本之间的细微差别。</P> <p CLASS="WF"> 在开始的时候,需要在您的事件处理函数中定义一个参数变量,准备接收可能传入的事件对象。然后,通过简单的条件表达式把浏览器的事件对象赋值给上述的参数变量:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">function myFunc(evt) { evt = (evt) ? evt : ((window.event) ? window.event : "") // process event here }</SPAN> </pre> <p CLASS="WF"> 如果事件对象真的以参数的形式传进来了,则在函数内部,事件对象就被保留在 <code>evt</CODE> 这个局部变量中。如果这个参数是 <code>null</CODE>,而且浏览器的 <code>window</CODE> 对象包含有一个 <code>event</CODE> 属性,则 <code>window.event</CODE> 对象就会把自己赋值给 <code>evt</CODE> 变量。</P> <p CLASS="WF"> 然而,为了完成这个工作,还应该再包含一层或者多层条件控制,以便优雅地适应那些在事件模型中没有定义事件对象的的早期浏览器:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">function myFunc(evt) { evt = (evt) ? evt : ((window.event) ? window.event : "") if (evt) { // process event here } }</SPAN> </pre> <p CLASS="WF"> 为了把同样的方式应用到所有事件处理函数的构建中,您可以定义一个函数来兼容两种事件,即由绑定的标识属性显式传入的事件对象,以及由绑定的事件属性隐式传入的事件对象。这样即使您在开发过程中改变了事件绑定的风格,这个函数也不必改变。</P> <h2 CLASS="WF"><font SIZE="4">瑞典自助餐式地选择事件对象</FONT></H2> <p CLASS="WF"> 然而,建立一个指向事件对象的引用只是战斗的一部分。来自不同事件模型的每一个事件对象都拥有自己的一套属性,以容纳事件的细节。下面的表格列出了最常用的属性,以及这些属性在上述三种事件对象类型中的名称。</P> <h3 CLASS="WF">表格 1. 流行的事件对象属性</H3> <table CELLSPACING="0" CELLPADDING="5" BORDER="1"> <tbody> <tr> <th CLASS="WF">描述</TH> <th CLASS="WF">NN4</TH> <th CLASS="WF">IE4+</TH> <th CLASS="WF">W3C/Safari</TH> </TR> <tr> <td CLASS="WF">Event target</TD> <td CLASS="WF"><code>target</CODE></TD> <td CLASS="WF"><code>srcElement</CODE></TD> <td CLASS="WF"><code>target</CODE></TD> </TR> <tr> <td CLASS="WF">Event type</TD> <td CLASS="WF"><code>type</CODE></TD> <td CLASS="WF"><code>type</CODE></TD> <td CLASS="WF"><code>type</CODE></TD> </TR> <tr> <td CLASS="WF">X coordinate on page</TD> <td CLASS="WF"><code>pageX</CODE></TD> <td CLASS="WF">*</TD> <td CLASS="WF"><code>pageX</CODE></TD> </TR> <tr> <td CLASS="WF">Y coordinate on page</TD> <td CLASS="WF"><code>pageY</CODE></TD> <td CLASS="WF">*</TD> <td CLASS="WF"><code>pageY</CODE></TD> </TR> <tr> <td CLASS="WF">Mouse button</TD> <td CLASS="WF"><code>which</CODE></TD> <td CLASS="WF"><code>button</CODE></TD> <td CLASS="WF"><code>button</CODE></TD> </TR> <tr> <td CLASS="WF">Keyboard key</TD> <td CLASS="WF"><code>which</CODE></TD> <td CLASS="WF"><code>keyCode</CODE></TD> <td CLASS="WF"><code>keyCode</CODE></TD> </TR> </TBODY> </TABLE> <span CLASS="WF"><br/></SPAN> <p CLASS="WF">标注*的属性值可以通过对 <code>event.clientX + document.body.scrollTop</CODE> 或者 <code>event.clientY + document.body.scrollTop</CODE> 进行求值来得到。</P> <p CLASS="WF">Macintosh 版本的IE5在通常情况下都遵循 IE4+ 的事件对象模型,但是有一个例外,即 IE5/Mac 的事件对象既定义了 <code>srcElement</CODE> 属性,也定义了 <code>target</CODE> 属性,这两个属性都指向接收事件的元素。</P> <p CLASS="WF">需要抽象的最重要的事件对象属性可能得算指向接收事件的 HTML 元素的引用。NN4 和 W3C 的事件对象采用相同的属性名(<code>target</CODE>),而 IE4+ 的事件对象则使用 <code>srcElement</CODE> 属性。这时候,对象检测技术(而不是费力劳神而又具有危险倾向的浏览器版本识别方法)再次拯救了我们。对于那些非文本容器的元素,一个简单的条件表达式就可以轻松处理脚本语法上的差别:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">var elem = (evt.target) ? evt.target : evt.srcElement</SPAN> </pre> <p CLASS="WF"> 从现在开始,您的脚本就可以读写任何浏览器对象模型公布出来的元素对象属性了。</P> <h2 CLASS="WF"><font SIZE="4">W3C DOM结点的事件目标</FONT></H2> <p CLASS="WF">W3C DOM 的结点架构使得文档中的每一个结点都可以接收事件。在支持这一架构的浏览器中,发生在嵌套文本顶上的事件并不调用分配给文本容器的事件处理器,相应的文本结点才是该事件的目标结点。考虑如下场景:</P> <p CLASS="WF">在<a HREF="http://developer.apple.com.cn/internet/webcontent/examples/eventsexample1_source.html" mce_HREF="http://developer.apple.com.cn/internet/webcontent/examples/eventsexample1_source.html" TARGET="_blank">事件实例</A>,当鼠标的指针在一个 SPAN 元素包含的文本顶上滚动时,该文本就会被高亮显示。 事件绑定的过程通过对象属性在 <code>init()</CODE> 函数中进行。从表面上看,当用户在 SPAN 元素顶上滚动鼠标时,<code>onMouseOver</CODE> 事件动作函数就为该元素指派一个与风格表单规则相关联的类名(<code>highlight</CODE>),该风格规则把文本的显示风格定义为粗体,黄色背景;而在 <code>onMouseOut</CODE> 函数中,则把风格恢复为原始的版本(类 <code>normal</CODE>)。请注意一个 <code>toggleHighlight()</CODE> 函数是如何在事件对象的 <code>type</CODE> 属性的帮助下,执行两个动作的(该属性在所有事件模型对象中的名称是相同的)。请<a HREF="http://developer.apple.com.cn/internet/webcontent/examples/eventsexample1.html" mce_HREF="http://developer.apple.com.cn/internet/webcontent/examples/eventsexample1.html" TARGET="_blank">试一下这个事件实例</A>。</P> <p CLASS="WF">但是如果您把例子装载到 NN6,则鼠标事件的真正目标就是 SPAN 元素中的文本结点了。本文并不讨论事件的传播机制,但是请相信,W3C DOM 事件模型的缺省行为会使事件沿着结点的包含层次向上传播(和 IE4+ 中事件通过元素容器向上传播的机制很类似)。因此,在这个事件实例中。鼠标事件会从其真正的目标向上传递到文本结点的容器(也就是 SPAN 元素)。这些事件触发了 SPAN 元素中相应的事件处理器。</P> <p CLASS="WF">虽然事件处理器属于 SPAN 元素,事件对象还是保留文本对象的引用,并将它作为事件的原始目标。然而,只有对文本结点的容器进行动作,才能修改它的风格。为了实现 <code>toggleHighlight()</CODE> 函数的等价操作,使之可以修改SPAN容器的 <code>className</CODE> 属性,该函数需要派生出一个指向文本结点容器的引用。</P> <p CLASS="WF">一个策略是使用 W3C DOM 事件对象的 <code>currentTarget</CODE> 属性,该属性返回一个处理事件的结点的引用。脚本中的决策树需要考虑这个属性,增加代码之后的 <code>toggleHighlight()</CODE> 函数如下所示:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">function toggleHighlight(evt) { evt = (evt) ? evt : ((window.event) ? window.event : "") if (evt) { var elem if (evt.target) { if (evt.currentTarget && (evt.currentTarget != evt.target)) { elem = evt.currentTarget } else { elem = evt.target } } else { elem = evt.srcElement } elem.className = (evt.type == "mouseover") ? "highlight" : "normal" } }</SPAN> </pre> <p CLASS="WF">另一个可选的方法是考察由 <code>target</CODE> 属性返回的对象的 ro<code>nodeType</CODE> 属性。一个能够把事件定向给文本结点的浏览器,也可以把一个文本结点的 <code>nodeType</CODE> 属性值报告为3,而不是报告为元素结点的类型(其值为1)。如果事件的目标是一个文本结点,则脚本程序就可以通过该文本结点的 <code>parentNode</CODE> 属性来得到其上级元素结点的引用。这种方法的决策树在某种程度上得到更多的改进:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">function toggleHighlight(evt) { evt = (evt) ? evt : ((window.event) ? window.event : "") if (evt) { var elem if (evt.target) { elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target } else { elem = evt.srcElement } elem.className = (evt.type == "mouseover") ? "highlight" : "normal" } }</SPAN> </pre> <p CLASS="WF">如果您正在用遵循 W3 的浏览器阅读本文,则请<a HREF="http://developer.apple.com.cn/internet/webcontent/examples/eventsexample2.html" mce_HREF="http://developer.apple.com.cn/internet/webcontent/examples/eventsexample2.html" TARGET="_blank">尝试这个修改过的版本</A>,看看鼠标滚动时的风格变化。</P> <p CLASS="WF">这个页面使用了嵌入到<a HREF="http://developer.apple.com.cn/internet/webcontent/examples/eventsexample1_source.html" mce_HREF="http://developer.apple.com.cn/internet/webcontent/examples/eventsexample1_source.html" TARGET="_blank">事件实例</A>中的最新版本的 <code>toggleHighlight()</CODE> 函数,展示了如何使用 JavaScript 为那些能够显示期望效果的浏览器增加额外的价值,同时也可以那些基本的内容提供给仍然使用着较老版本或者不支持脚本编程的浏览器的用户,只不过在模式上不那么动人和便于交互。</P> <h2 CLASS="WF"><font SIZE="4">一个事件处理函数的模板</FONT></H2> <p CLASS="WF"> 并不是每个事件处理函数都处理页面元素对象中同样的属性或者行为,但是,从上文的讨论可以派生出来的一个模板,您可以在这个模板的帮助下开始编码。模板如下:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">function functionName(evt) { evt = (evt) ? evt : ((window.event) ? window.event : "") if (evt) { var elem if (evt.target) { elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target } else { elem = evt.srcElement } if (elem) { // process event here } } }</SPAN> </pre> <p CLASS="WF"> 请把第一行的函数名替换为您希望的函数名,并在注视指示的地方开始书写具体事件的代码。这个格式应该可以为您提供一个起点,适合于您采用的任何跨浏览器的事件绑定风格。如果您需要在一个页面中多次使用这个格式,则可以进一步精简代码,即把读取目标的代码抽象成一个可重用的工具函数,然后在每一个事件处理函数中进行调用:</P> <pre CLASS="sourcecodebox"> <span CLASS="WF">// shared function function getTargetElement(evt) { var elem if (evt.target) { elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target } else { elem = evt.srcElement } return elem } function functionName(evt) { evt = (evt) ? evt : ((window.event) ? window.event : "") if (evt) { var elem = getTargetElement(evt) if (elem) { // process event here } } }</SPAN> </pre> <p CLASS="WF"> 有了这类框架,您现在应该可以把更多的注意力集中在各个事件处理函数要求的具体动作中了。</P> </DIV></script>

分享到:
评论

相关推荐

    事件选择模型经典源码

    常见的事件选择模型有三种:轮询模型、多路复用I/O(如select、poll、epoll)和异步非阻塞I/O(如kqueue、AIO)。这些模型各有特点,适用于不同的场景。 1. 轮询模型:服务器轮询检查每个连接的状态,如果发现有可...

    手写DOM事件模型

    DOM事件模型分为三个层次:**事件冒泡(Event Bubbling)**、**事件捕获(Event Capturing)**和**DOM2级事件模型**。事件冒泡是从最深的节点开始,逐级向上层节点传播事件;事件捕获则相反,从最外层节点开始,向下...

    javascript事件模型代码

    这些方法允许更灵活地添加、移除和触发事件监听器,同时支持事件冒泡和事件捕获,以及处理多个事件监听器。 4. JavaScript事件流 事件流描述了事件如何在文档结构中传播。主要有三种事件流: - **冒泡流**:事件...

    C++API事件选择模型

    - Boost.Asio是一个功能强大的跨平台通信库,支持多种事件模型,包括select、poll和epoll。 总的来说,C++ API的事件选择模型是解决并发和异步问题的关键技术之一,通过合理选择和使用这些模型,开发者可以构建出...

    VB三维模型程序完整版

    这个【VB三维模型程序完整版】项目为初学者和有经验的VB程序员提供了一个很好的实践平台,可以深入理解三维图形编程的基本原理,同时也展示了VB在图形处理领域的强大能力。通过研究源代码,开发者不仅可以学习到VB的...

    three官网所有模型

    使用这些模型时,你需要了解如何在Three.js中设置相机、光源和场景,以及如何将模型与交互事件绑定,如点击、拖动等。同时,理解模型的单位系统、坐标系统以及如何调整其大小和位置至关重要。此外,你可能还需要对...

    代码 传染病的SI SIS SIR 三种数学建模模型.rar

    "SI、SIS、SIR"这三种模型是流行病学中常用的数学模型,用于模拟疾病传播的过程。下面将详细介绍这些模型以及它们在实际中的应用。 1. SI模型(Susceptible-Infected模型): SI模型是最基础的传染病模型之一。在...

    5种winsock_IO模型

    #### 三、异步选择模型(WSAAsyncSelect) 异步选择模型使用`WSAAsyncSelect`函数实现。它通过向操作系统注册一个窗口的消息句柄,当指定的套接字上发生特定事件时,操作系统会向注册的窗口发送一条消息。这种方式...

    Windows Socket五种I/O模型——代码全攻略

    本文将详细介绍Windows Socket支持的五种I/O模型,并提供相应的代码示例。 #### 一、阻塞I/O模型 阻塞I/O是最常见的I/O模型,其特点是当调用I/O操作时,如果操作未能立即完成,则调用线程会被阻塞,直到I/O操作...

    计算机辅助设计基础_三维模型的显示.rar_blackfde_opengl_三维_三角网格_读入三维模型

    计算机辅助设计(CAD)是现代工程和设计领域中不可或缺的一部分,而OpenGL则是一种跨语言、跨平台的图形库,用于渲染二维和三维图像。在这个主题中,“计算机辅助设计基础_三维模型的显示.rar”文件主要关注如何使用...

    大气扩散模型JAVA代码

    JAVA作为一种广泛使用的编程语言,具有跨平台性、面向对象以及丰富的库支持等优点,使其成为构建这种模型的理想选择。 首先,大气扩散模型的基础是理解污染物在大气中的运动规律。这些模型通常基于物理学原理,如...

    Socket IO模型介绍

    第三种是`WSAEventSelect`模型,它与`WSAAsyncSelect`类似,但使用事件对象而非消息队列进行事件通知。开发者可以创建和关联事件对象,当Socket事件发生时,相应的事件对象被置为信号状态,从而触发事件处理。 第四...

    javascript大事模型介绍_.docx

    本文将详细介绍三种主要的事件模型:原始事件模型、DOM2事件模型以及IE事件模型,并探讨它们的差异和使用方法。 首先,原始事件模型是所有浏览器都支持的基础模型。在此模型中,事件分为“输入事件”(如`onclick`...

    AE+vb环保模型,包括水污染模型,大气污染模型及爆炸模型.rar

    开发者可能使用ArcEngine的空间分析功能,如缓冲区分析、网络分析等,来确定污染源的影响范围,同时结合数学模型预测污染物在水体中的迁移和转化。 大气污染模型:大气污染模型主要关注污染物在大气中的扩散、沉积...

    盘古天气大模型介绍PPT

    盘古天气大模型采用了独特的3DEST网络结构,该结构是专门为处理三维空间数据而设计的。相比于传统的二维深度神经网络,3DEST网络能够更好地捕捉大气中各要素(如温度、湿度、风速等)随时间和空间的变化规律,从而...

    文档级无触发词事件抽取联合模型.pdf

    - **端到端模型**:通过同时训练实体识别、事件类型检测及事件论元抽取三个子模块,实现了端到端的事件抽取过程,有效避免了传统管道式方法中可能出现的误差累积问题。 5. **性能评估**: - **实验结果**:在单...

    效果超棒的Webgl模型-人体肺

    WebGL是一种基于OpenGL标准的JavaScript API,用于在任何兼容的现代网页浏览器中呈现交互式的2D和3D图形,无需插件支持。这个名为“效果超棒的Webgl模型-人体肺”的资源,显然是一个利用WebGL技术创建的、展示人体...

    几种计算机软件应用体系结构模型

    7. 并行和分布式架构:在这些模型中,任务被分配到多台计算机上同时执行,以提高性能和处理大量数据的能力。例如,MapReduce用于大规模数据处理,而分布式文件系统如Hadoop则支持大数据的存储和分析。 8. 事件驱动...

    零售数据模型.pdf

    逻辑模型的设计确保了数据库的高效运行,同时也便于后续的数据分析工作。 ### 三、维度模型 维度模型是一种广泛应用于数据仓库的设计方法,尤其适合于零售业这类具有大量交易记录的行业。它将数据分为事实表和维度...

    winsock io模型源码

    我们将围绕WSAAsyncSelect、WSAEventSelect以及select这三种常用的Winsock异步I/O模型进行详细解析。 1. **WSAAsyncSelect模型**: WSAAsyncSelect是Windows Socket API提供的一种异步事件通知机制。在VC++中,...

Global site tag (gtag.js) - Google Analytics