常见知识点汇总(二):事件
Javascript与HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。
事件流
事件冒泡
IE的事件流叫做事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
所有的现代浏览器都支持事件冒泡。
事件捕获
事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件达到预订目标之前捕获它。
仅在有特殊需要时再使用事件捕获。
DOM事件流
DOM2级事件规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
即使DOM2级事件规范明确要求捕获阶段不会设计事件目标,但IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都会在捕获阶段触发事件对象上的事件。结果,就是有两个机会在目标对象上面操作事件。
事件处理程序
HTML事件处理程序
|
|
|
|
事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码。
在HTML中指定事件处理程序有2个缺点:
时差问题:用户可能会在HTML元素一出现在页面上就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件。可以使用try-catch来捕获错误:
1<input type="button" value="Click Me" onClick="try{showMessage();}catch(ex){}">这样扩展事件处理程序的作用域链在不同浏览器中会导致不同结果。不同javascript引擎遵循的标识符解析规则略有差异,很可能在访问非限定对象成员时出错。
DOM0级事件处理程序
|
|
DOM2级事件处理程序
DOM2级事件定义了两个方法,用于处理指定和删除处理程序的操作:addEventListener()和removeEventListener()。所有DOM节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名,作为事件处理程序的函数和一个布尔值。最后一个布尔值如果是true,标示在捕获阶段调用事件处理函数,flase则表示在冒泡阶段调用事件处理程序。
通过addEventListener()添加的事件处理程序只能通过removeEventListener()移除。移除时传入的参数与添加处理程序时使用的参数相同。这也意味着通过addEventListener()添加的匿名函数将无法移除。
IE事件处理程序
IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。由于IE只支持事件冒泡,所以通过attachEvent添加的事件处理程序都会被添加到冒泡阶段。
事件对象
在触发DOM上某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。包括导致事件的元素,事件的类型,以及其他与特定事件相关的信息。
DOM中的事件对象
兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0级或DOM2级),都会传入event对象。
- 在事件处理程序内部,对象this始终等于currentTarget的值,target则只包含事件的实际目标。
- 要阻止特定事件的默认行为,可以使用preventDefault()方法。只有cancelable属性设置为true的事件,可以使用preventDefault()来取消其默认行为。
- stopPropagation()方法用于立即停止事件在DOM层次中的传播,即取消进一步的事件捕获或冒泡。
- 事件的eventPhase属性,可以用来确定事件当前正位于事件流的哪个阶段;如果是在捕获阶段调用程序,那么eventPhase等于1;如果事件处理程序处于目标对象上,则eventPhase等于2;如果是在冒泡阶段调用事件处理,则eventPhase等于3。
IE中的事件对象
与访问DOM中的Event对象不同,要访问ie中的event对象有几种不同的方式,取决于指定事件处理程序的方法。
在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在。
若事件处理程序是使用attachEvent()添加的,那么就会有一个event对象作为参数被传入事件处理程序函数中。
常用的event属性:
- cancelBubble 默认为false,但将其设置为true就可以取消事件冒泡。(与DOM的stopProgagation()方法作用相同)
- returnValue 默认为true,但将起设置为false就可以取消事件的默认行为(与DOM的preventDefault()方法作用相同)
- srcElement 事件的目标。(与DOM的target属性相同)
常用事件类型
UI事件
- load
- unload
- abort
- error
- select
- resize
- scroll
焦点事件
- blur
- DOMFocusIn
- DOMFocusOut
- focus
- focusin
- focusout
鼠标与滚轮事件
- click
- dblclick
- mousedown
- mouseenter
- mouseleave
- mousemove
- mouseout
- mouseover
- mouseup
- mousewheel
- button
键盘与文本事件
- keydown
- keypress
- keyup
- textInput
复合事件
- compositionstart
- compositionupdate
- compositionend
变动事件
- DOMSubtreeModified
- DOMNodeInserted
- DOMNodeRemoved
- DOMNodeInsertedIntoDocument
- DOMNodeRemovedFromDocument
- DOMAttrModified
- DOMCharacterDataModified
HTML5事件
- contextmenu
- beforeunload
- DOMContentLoaded
- readystatechange
- pageshow/pagehide
- hashchange
设备事件
- orientationchange
- MozOrientation
- deviceorientation
- devicemotion
触摸与手势事件
- touchstart
- touchmove
- touchend
- touchcancel
- touches
- targetTouchs
- changeTouches
- gesturestart
- gesturechange
- gestureend
事件委托
对”事件处理程序过多“问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
以下面的HTML代码为例:
其中包含3个鼠标移入/移出后执行操作的列表项。按照传统的做法,需要想下面这样为它们添加3个事件处理程序。
如果在复杂的web应用程序中,对所有li都采用这种方式,那么li一多就会有大量的代码用于添加事件处理程序。使用事件委托,只需在DOM树中尽量最高的层次上添加一个事件处理程序:
这段代码里,我们使用事件委托只为ul元素添加了一个onclick事件处理程序,只取得了一个DOM元素,只添加了一个事件处理程序,这样占用内存更少,性能更高。
并且当ul内动态添加新的li元素时,事件也可以生效。