JavaScript 浏览器事件处理机制详解:从0级到2级DOM
本文详细解析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事件的情况下,执行结果如下:
可见,事件是由内向外层的元素依次触发的。(一般教材上的说法是向上浮升,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
vtk.js 渲染窗口黑屏或无内容显示的常见原因及排查
2026-11-05 17:30:30
js-cookie 安装与基础用法:set、get、remove 详解
2026-11-05 16:35:06
适合JavaScript初学者的实战项目:制作简易待办事项列表
2026-11-05 16:17:07
JS打开新标签页时怎么通过URL传递参数
2026-11-05 12:21:08
sigma.js 自定义节点样式:设置颜色、大小及标签显示的技巧
2026-11-05 09:55:00
