JavaScript与HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或处理程序)来预定事件,以便时间发生时执行相应的代码。这种在传统软件工程中被称为观察员模式的模型,支持页面的行为(JavaScript代码)与页码。这种在传统软件工程中被称为观察员模式的模型,支持页面的行为(JavaScript代码)与页面的外观(HTML和CSS代码)之间的松散耦合。
一、事件流
事件流描述的是页面中接收事件的顺序。
1 事件冒泡
IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接受,然后逐级向上传播到较为不具体的节点(文档)。
2 事件捕获
事件捕获的思想是不太具体的节点应该更早接受到事件,而最具体的节点应该最后接收到事件。
3 DOM事件流
“DOM2级事件”规定的事件流包括三个阶段:事件捕获节点、处于目标阶段和事件冒泡阶段。
二、事件处理程序
1 HTML事件处理程序
某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的HTML特性来指定。这个特性的值应该是能够执行的JavaScript代码。
在HTML中指定事件处理程序的缺点如下。
- 存在一个时差问题。因为用户可能会在HTML元素一出现在页面上就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件。
- 扩展事件处理程序的作用域链在不同的浏览器中会导致不同的结果。不同JavaScript引擎遵循的标识符解析规则略有差异,很可能会在访问非限定对象成员时出错。
- HTML与JavaScript代码紧密耦合。
2 DOM0级事件处理程序
使用DOM0级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序会在事件流的冒泡阶段被处理。
3 DOM2级事件处理程序
“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListenter()和removeEventListener()。所有DOM节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。
与DOM0级方法一样,这里添加的事件处理程序也是在其依附的元素的作用域中运行。使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。
大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。
4 IE事件处理程序
IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。由于IE8及更早版本只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。
三、事件对象
1 DOM中的事件对象
兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0级或DOM2级),都会传入event对象。
在通过HTML特性指定事件处理程序时,变量event中保存着event对象。
所有事件都会都会有下表列出的成员。
属性/方法 | 类型 | 读/写 | 说明 |
bubbles | Boolean | 只读 | 表明事件是否冒泡 |
cancelable | Boolean | 只读 | 表明是否可以取消事件默认行为 |
currentTarget | Element | 只读 | 其事件处理程序当前正在处理事件那个元素 |
defaultPrevented | Boolean | 只读 | 为true表示已经调用了preventDefault()(DOM3级事件中新增) |
detail | Integer | 只读 | 与事件相关的细节信息 |
eventPhase | Integer | 只读 | 调用事件处理程序的阶段:1表示捕获阶段,2表示“处于目标”,3表示冒泡阶段 |
preventDefault() | Function | 只读 | 取消事件的默认行为。如果cancelable是true,则可以使用这个方法 |
stopImmediatePropagation() | Function | 只读 | 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级事件中新增) |
stopPropagation() | Function | 只读 | 取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法 |
target | Element | 只读 | 事件的目标 |
trusted | Boolean | 只读 | 为true表示事件是浏览器生成的。为false表示事件是由开发人员通过JavaScript创建的(DOM3级事件中新增) |
type | String | 只读 | 与事件关联的抽象视图。等同于发生事件的window对象 |
在事件处理程序的内部,对象this始终等于currentTarget的值,而target则只包含事件的实际目标。
2 IE中的事件对象
与访问DOM中的event对象不同,要访问IE中的event对象有几种不同的方式,取决于指定事件处理程序的方法。在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在。
如果事件处理程序是使用attachEvent()添加的,那么就会有一个event对象作为参数被传入事件处理程序函数中。
所有事件对象都会包含下表所列的属性和方法。
属性/方法 | 类型 | 读/写 | 说明 |
cancelBubble | Boolean | 读/写 | 默认值为false,但将其设置为true就可以取消事件冒泡 |
retureValue | Boolean | 读/写 | 默认值为true,但将其设置为false就可以取消事件的默认行为 |
srcElement | Element | 只读 | 事件的目标 |
type | String | 只读 | 被出发的事件的类型 |
四、事件类型
Web浏览器中可能发生的事件有很多类型。如前所述,不同的事件类型具有不同的信息,而“DOM3级事件”规定了以下几类。
- UI(User Interface,用户界面)事件,当用户与页面上的元素交互时出发;
- 焦点事件,当元素获得或失去焦点时触发;
- 鼠标事件,当用户通过鼠标在页面上执行操作时触发;
- 滚轮事件,当使用鼠标滚轮(或类似设备)时触发;
- 文本事件,当在文档中输入文本时触发;。
- 键盘事件,当用户通过键盘仔页面上执行操作时触发;
- 合成事件,当为IME(Input Method Editor,输入法编辑器)输入字符时触发;
- 变动(mutation)事件,当底层DOM结构发生变化时触发。
1 UI事件
现有的UI事件如下:
- DOMActivate:表示元素已经被用户操作(通过鼠标或键盘)激活。这个事件在DOM3级事件中被废弃。
- load:当页面完全加载后在window上面触发,当所有框架都加载完毕时在框架集上面触发,当图像加载完毕时在<img>元素上面触发,或者当嵌入的内容加载完毕时在<object>元素上面触发。
- unload:当页面完全卸载后在window上面触发,当所有框架都卸载后在框架集上面触发,或者当前软的内容卸载完毕后在<object>元素上面触发。
- abort:在用户停止下载过程时,如果嵌入的内容没有加载完,则在<object>元素上面触发。
- error:当发生JavaScript错误时在window上面触发。
- select:当用户选择文本框(<input>或<textarea>)中的一或多个字符时触发。
- resize:当窗口或框架的大小变化时在window或框架上面触发。
- scroll:当用户滚动带滚动条的元素中的内容时,在该元素上面触发。<body>元素中包含所加载页面的滚动条。
2 焦点事件
- blur
- DOMFocusIn
- DOMFocusOut
- focus
- focusin
- focusout
3 鼠标与滚轮事件
- click
- dblclick
- mousedown
- mouseenter
- mouseleave
- mouseenter
- mouseout
- mouseup
4 键盘与文本事件
有三个键盘事件,简述如下:
- keydown
- keypress
- keyup
在用户按了一下键盘上的字符键时,首先会触发keydown事件,然后紧跟着是keypress事件,最后会触发keyup事件。其中keydown和keypress都是在文本框发生变化之前被出发的;而keyup事件则是在文本框已经发生变化之后被触发的。如果用户按下了一个字符键不放,就会重复触发keydown和keypress事件,知道用户松开改键为止。
1)键码
2)字符编码
3)DOM3级变化
五、内存和性能
1 事件委托
2 移除事件处理程序
六、模拟事件
1 DOM中的事件模拟
可以在document对象上事件createEvent()方法创建event对象。这个方法接受一个参数,即表示要创建的事件类型的字符串。在DOM2级中,所有这些字符串都是用英文负数形式,而在DOM3级中都变成了单数。这个字符串可以是下列几个字符串之一。
- UIEvents
- MouseEvents
- MutationEvents
- HTMLEvents
2 自定义事件
DOM3级还定义了“自定义事件”。自定义事件不是由DOM原生触发的,它的目的是让开发人员创建自己的事件。
- type(字符串):触发的事件类型,例如“keydown”。
- bubbles(布尔值):表示事件是否该冒泡。
- cancelable(布尔值):表示事件是否可以取消。
- detail(对象):任意值,保存在event对象的detail属性中。