JavaScript 浏览器事件处理机制详解:从0级到2级DOM

作者:像素猫时间:2026-10-24 15:04:33浏览:249

本文详细解析JavaScript中浏览器事件的处理机制,涵盖0级DOM的内联与传统注册方式,以及2级DOM的addEventListener与attachEvent方法。重点讲解事件对象属性的跨浏览器差异、事件冒泡原理及取消方法,并提供兼容IE与W3C标准的代码实现方案。

JavaScript事件处理概述

事件机制本身概念直观,前端开发中常用的事件类型包括以下几种:


事件 描述
abort 图片被阻止而不能加载
blur,focus 失去焦点,获得焦点
change 适用于表单元素,当元素使其焦点的时候判断是否发生改变
click,dblclick 单击,双击
keydown,keyup,keypress 按下键,键离开,按下键的时候触发,注意keypress只对数字字母键有效
load 加载图片或者页面的时候
mousedown,mouseup 按下键,放开键
mouseover,mouseout over是当鼠标进入的时候出发,out是离开的时候触发
mousemove 鼠标移动
reset,submit 重置和提交表单

上述列举仅为常见事件的概览,如需完整且详尽的事件列表,建议查阅相关的官方开发手册。



1. 0级DOM上的事件处理

0级DOM事件处理模型

0级DOM事件处理模型出现较早,至今仍在广泛使用,该技术自IE4.0版本起便已得到支持。



1.1 事件注册

事件注册方式

下文将重点阐述如何为事件添加处理程序,即实现事件响应函数的注册。



(1)内联注册(inline registration)



这是最基础的一种注册方式,即将事件响应函数直接设置为HTML标签的一个属性。例如,属性值可以是具体的代码片段,但更多情况下是函数调用。事件句柄通常由事件名称加上前缀“on”构成。


 <html> <head> <title>event sample</title> <style type="text/css"> #adiv{ width:200px; height:200px; background-color:#00aa00; } </style> </head> <body> <div id="adiv" onmouseover="this.innerHTML+='OK'" > a </div> </body> </html> 

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]


该方法的优点在于实现简单,所有浏览器均支持。然而,其缺点是将JavaScript代码与HTML结构混杂,且无法动态添加多个事件响应程序,也无法在运行时动态注册事件。



(2)传统模式(traditional registration)

此模式通过将事件作为DOM对象的属性进行添加。具体示例如下:


  

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]


1.2 事件的参数(Event对象)

事件对象与跨浏览器兼容

部分事件处理程序需要获取更详细的事件信息,例如click事件发生的具体坐标。这些信息通过事件参数传递给处理程序。需要注意的是,IE事件模型与W3C事件模型在实现方式上存在差异。



在IE模型中,event对象被作为window对象的一个属性存在;而在W3C模型中,event对象则作为处理程序的第一个参数传入。以下以click事件为例,分别编写适用于IE和支持W3C标准浏览器的程序代码。


 <html> <head> <title>event sample</title> <style type="text/css"> #adiv{ width:200px; height:200px; background-color:#00aa00; } </style>  </head> <body> <div id="adiv" onclick="W3CClick(event)" >a </div> <div id="result" style="font-size:small; font-family:Verdana"> </div> </body> </html> 

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]


上述页面代码展示了如何获取click事件对象的所有属性。前例为W3C浏览器所用方法,若需在IE下运行,只需将onclick属性值改为“IEClick()”即可。需注意,W3CClick函数中的参数名必须严格为“event”。虽然打印出的属性众多,但经过FF3.5、Chrome3、IE8(标准模式及兼容模式)测试,共有的属性并不多,实际上只有这些共有属性具有通用意义,它们包括:



altKey, shiftKey, ctrlKey:分别表示是否按下Alt、Shift或Ctrl键



clientX, clientY:表示客户区坐标(相对于浏览器窗口),screenX, screenY:表示屏幕区坐标



type:事件类型

尽管事件参数的传递方式在不同模型间存在差异,但这并未给跨浏览器代码编写带来过大困扰。只需在函数起始处判断window.event是否存在即可解决兼容性问题。


具体代码如下:

 
function BothClick(args) {
var evnt = window.event ? window.event : args;
alert(evnt.clientX);
} 

注册句柄为:<div id="adiv" onclick="BothClick(event)" >a</div>。如果采用第二种方式(传统模式)注册句柄,则无需进行上述特殊处理。



1.3 事件的浮升

事件冒泡与取消机制

页面中的DOM对象通常存在重叠关系,例如一个div内部包含若干子div或其他元素。当某一事件触发时,多个元素可能同时受影响且都绑定了相应的事件处理程序。此时,哪些处理程序会被执行?以何种顺序执行?这正是本节讨论的核心。通常情况下,一个事件被多个句柄捕获的情形并不常见。先看一个示例(CSS样式已省略):


  </head> <body onclick="body_click()"> <div id="out" onclick="out_click()"> Outer Div <div id="innerdiv" onclick="inner_click()" > Inner Div </div> </div> <div id="res"> </div> </body> 

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]


在body、外层div和内层div均响应click事件的情况下,执行结果如下:


image 

可见,事件是由内向外层的元素依次触发的。(一般教材上的说法是向上浮升,bubbling,但我认为“向上”一词具有歧义,初学者容易误认为内层元素在视觉上位于上层,因为它能覆盖外层元素)。使用0级DOM注册的事件,其浮升方法在IE和W3C模型中是统一的。



1.4 浮升的取消


有时我们需要在响应某个事件后,阻止外层元素继续响应,即取消事件的浮升。IE和W3C模型取消浮升的方法不一致:IE通过设置事件对象的cancelBubble属性为true来实现,而W3C则是调用事件对象的stopPropagation方法。



例如,将上述示例修改为:


代码如下:

 
function inner_click(arg){
var evnt=window.event?window.event:arg;
var dis=document.getElementById("res");
dis.innerHTML+="Inner Click <br/>";
if(evnt.stopPropagation){
evnt.stopPropagation();
}else{
evnt.cancelBubble=true;
} 
<div id="innerdiv" onclick="inner_click(event)" >

其他代码保持不变,此时只能看到一行输出,表明内层事件处理完毕后,外层事件未被触发。



1.5 事件处理函数中的this


在事件处理函数中,this关键字指向的是触发该事件的目标对象。



2级DOM事件处理模型

接下来介绍2级DOM的事件句柄注册方式。这是一种较新的方法,不依赖于特定的事件句柄属性。W3C规定的标准方式是:



object.addEventListener(‘event', function, boolean)



第一个参数是事件名,第二个参数是事件响应函数,第三个参数如果是true,则事件函数在冒泡阶段被触发;如果是false,则在捕获阶段被触发。W3C规定事件发生包含两个阶段:首先是捕获阶段,事件从最外层元素向内层传递,依次触发相应的事件处理函数;然后是冒泡阶段,事件从最内层元素向外层传递。看一个示例:


 <html> <head> <title>DOM 2 Event</title>  </head> <body > <div id='testDiv' style="width:100px;height:100px;background-color:gray"></div> <body> </html> 

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]


点击灰色框,会依次弹出“body true, div true, div false, body false”。遗憾的是,IE不支持这种方式,即使是最新的IE8版本也不支持。不过,IE提供了类似的注册事件方法,名为attachEvent。该方法没有第三个参数,仅支持冒泡阶段的事件响应。attachEvent函数传递事件参数的方式与W3C一致,也是通过event参数传递,但其函数内部的this指向并非触发事件的对象,而是永远指向window。在event对象中,有一个属性指向触发该事件的对象:W3C中是target,IE中是srcElement。在符合W3C规范的浏览器中,事件处理函数中的this和event.target指向同一个对象。下面的程序展示了一个兼容IE和W3C的事件处理程序:


 <html> <head> <title>DOM 2 Event</title>  </head> <body> <div id='testDiv' style="width:100px;height:100px;background-color:gray"> Hello World. </div> </body> </html> 

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]


事件处理程序中,W3C和IE模型还存在诸多不一致之处,处理起来较为繁琐。好在大多都有较好的解决方案。更多信息请参考http://www.quirksmode.org/js/events_events.html

作者最新文章