事件,像click,load,mouseover都是用户或者浏览器执行的某种动作,都会触发某些事件。在触发事件的时候,我们需要有一个事件监听函数(事件处理程序)来响应事件。事件监听函数的名字都是“on”+事件名组成的,像click的事件监听函数就是onclick。
HTML事件监听程序
对于元素支持的每种事件,都可以在元素中指定一个与事件监听函数同名的特性。特性的值是要执行的js代码,比如下面的例子:
|
|
如果函数体内容多的话,需要把js代码放到javascript标签内,如下:
|
|
但是这样指定事件监听函数让得HTML与Javascript紧密耦合,如果需要更换事件监听函数,那么HTML和javascripot代码都需要修改,所以为什么不干脆全部使用js来绑定和声明事件监听函数呢!
js事件监听程序
DOM0级事件处理程序
每个元素都有自己的事件处理程序属性,通常事件名都为小写,如:onclick,onmouseover,在绑定处理函数时需要先获得元素的引用,直接看一个简单的例子吧:
|
|
程序中的this指向的是当前元素,即btn,通过点取的方式,我们可以访问元素的任何属性和方法。
DOM2级事件处理程序
“DOM2级事件”定义了两个用于绑定事件和移除事件的方法:addEventListener()和removeEevntListener(),这两个方法在之前冒泡和捕获那一节已经介绍过了,就不过多说明了。
这两个方法都接收三个参数:
- 事件名(不带on)
- 事件处理函数
- 是否捕获
addEventListener()的优势在于可以为同一元素绑定多个方法,执行顺序由绑定先后决定。
在移除时传入的参数要与绑定时相同,这也意味着不能移除匿名函数
IE事件处理程序
IE实现两个类似的方法:attachEvent()和detachEvent(),之前同样也介绍过,下面就说一下特别的地方。
这两个方法都接收两个参数:
- 事件名
- 事件处理函数
DOM0级方法中事件处理程序会在元素的作用域内进行,而使用这两个方法时程序会在全局作用域中运行,因为this指向window。
和addEventListener()类似,attachEvent()可以为元素绑定多个方法,不过是后绑定的先运行。
跨浏览器的事件处理程序
为了让我们的代码可以在所有浏览器正常运行,我们可以自己编写一个兼容所有浏览器的事件处理程序。
事件对象
这算一个比较重要的点了,我们触发某个事件时,会产生一个事件对象event,其中包含着所有与时间有关的信息,如事件的类型,事件的目标(事件委托应用到),以及与特定事件相关的信息。例如,鼠标事件中,有包含鼠标位置的信息,键盘事件中则包含于按键相关的信息。浏览器虽然都支持event对象,但支持方式不尽相同。
DOM中的事件对象
当触发了事件时,兼容DOM的浏览器都自动会给我们的事件处理程序传入一个event对象,我们要做的只是在声明监听函数的时候加上一个event参数以便浏览器传入就ok了,如下:
下面列举type的属性及方法:
- type:事件类型
- bubbles:表明事件是否可以冒泡
- cancelable:表明是否可以阻止默认事件
- currentTarget:事件处理程序当前正在处理的元素,通常用target较多
- preventDefault():取消事件的默认行为,需要cancelable属性为True方可用,可用来定制自己的处理行为
- stopPropagation():取消事件的进一步捕获或者冒泡,需要bubbles为True方可用
- target:事件的真正目标
- eventPhase:确定事件当前正处于事件流的哪个阶段,1代表处于捕获阶段,2代表处于目标对象上,3代表处于冒泡阶段
在事件处理程序内部,this始终等于currentTarget的值,如果不使用事件委托,那么this,currentTarget,target的值相同.
IE中的事件对象
访问IE中的event的方式有几种,取决于绑定监听函数的方式。
如果是使用DOM0级方法添加的事件监听函数,那么event对象会作为window对象的一个属性存在。
|
|
如果通过attachEevent方法来绑定监听函数,那么event对象会自动传入我们我们的事件处理函数中。
同样,IE下的event对象也有一些属性和方法,大多都与DOM下的event属性方法对应:
- cancelBubble:取消冒泡,默认为false,与stopPropagation()对应
- returnValue:默认为true,置为false可阻止默认事件,与preventDefault()对应
- srcElement:与Dom中的target属性对应
- type:同DOM下的type
IE中事件处理程序中的this会随绑定方式的不同而变化,所以最好使用srcElement比较稳妥。
跨浏览器的事件对象
下面来实现事件对象的兼容写法:
|
|
事件类型
介绍完基本的事件监听函数和事件对象,接下来就应该介绍种类繁多的事件类型及应用了。
DOM3级事件规定了一下事件:
- UI(user Interface)事件,用户与元素交互时触发
- 焦点事件,元素获取或失去焦点时触发
- 鼠标事件,通过鼠标执行操作时触发
- 滚轮事件,使用滚轮时触发
- 文本事件,在文档中输入文本时触发
- 键盘事件,在键盘上执行操作触发
- 合成事件,在IME(输入法编辑器)输入字符触发
- 变动事件,底层DOM结构发生变化时触发
包括IE9在内的主流浏览器斗殴支持DOM2级事件,IE9也支持DOM3事件
UI事件
UI事件指的并不一定是与用户操作有关的事件,较常用的有:
- load:页面完全加载后在window上触发,当所有框架加载完在框架集上触发,当图像加载完毕是在img元素上触发
- unload:与上面类似,只不过是在写在的时候触发
- select:用户选择文本框中的字符时触发。
- resize:当窗口或框架大小发生改变时触发
- scroll:用户滚动带滚动条的元素中的内容时触发
这些事件都可以用HTML事件处理程序的方式实现。
根据DOM级事件规范,我们应该在document上处理load事件,但实际上所有浏览器在window上都实现了该事件,确保向后兼容。
焦点事件
焦点事件与document.hasFocus()及document.activeElement属性配合,可以知道用户在页面上的行踪。
焦点事件有以下这些:
- blur:元素失去焦点时触发,不会冒泡
- focus:元素获取焦点是触发,不会冒泡
- focusin:元素获取焦点时触发,冒泡,除了FF外基本都支持(DOM3)
- focusout:元素失去焦点触发,冒泡,除了FF外基本都支持(DOM3)
- DOMFocusOut:只有Opera支持,与focusout等价
- DOMFocusIn:只有Opera支持,与focusin等价
在页面中当焦点从一个元素移到另一个焦点上时,事件的触发顺序是这样的:
- focusout在失去焦点的元素上触发
- focusin在获得焦点的元素上触发
- blur在失去焦点的元素上触发
- DOMFocusOut在失去焦点的元素上触发
- focus在获得焦点的元素上触发
- DOMFoucusIn在获得焦点的元素上触发
要确定浏览器是否支持dom3的焦点事件,可以用以下代码
|
|
鼠标和滚轮事件
网页中用户大多的操作行为都是通过鼠标来实现的,DOM3级中实现了9个鼠标事件:
- click:用户单击鼠标左键和enter键时触发
- dblclick:用户双击鼠标左键时触发,DOM3将它纳入了标准
- mousedown:用户按下鼠标按钮还没放开时触发
- mouseup:用户释放鼠标按钮时触发
- mouseenter:鼠标光标首次移进目标元素内触发,此事件不冒泡,移进后代元素不会触发,DOM3将它纳入了标准
- mouseoutleave:鼠标光标移到元素范围之外时触发,事件不冒泡,移进后代元素不会触发,DOM3将它纳入了标准
- onmouseover:鼠标光标首次移进目标元素内触发,移进后代会触发
- onmouseover:鼠标光标移出目标元素内触发,移进后代会触发
总结:除mouseenter和mouseleave外,其他函数都会冒泡,也可以被取消默认行为。只有相继触发mousedown和onmouseup才会触发click事件。连续两次触发click才会引发dblclick事件。
这四个事件触发的先后顺序如下:
- mousedown
- mouseup
- click
- mousedown
- mouseup
- click
- dblclick
要确定浏览器是否支持DOM3和DOM3的鼠标事件,可以用以下代码
|
|
滚轮事件
鼠标能触发的还有一个滚轮事件,mousewheel,其实之前的博客中已经做了详细的介绍了。
鼠标事件中事件对象具有以下属性:
- clientX:事件发生时鼠标在视口中的水平坐标
- clientY:事件发生时鼠标在视口中的垂直坐标
- pageX:事件发生时鼠标在页面中的水平坐标(包含了滚动的距离)
pageY:事件发生时鼠标在页面中的垂直坐标(包含了滚动的距离)
以pageY为例,使用clientY和滚动信息就可以计算出pageY,这里我们需要通过document.body(混杂模式)和document.documentElement(标准模式)中的scrollLeft和scrollTop。
pageY = event.clientY + document.body.scrollTop || document.documentElement.scrollTop
- screenX:事件发生时鼠标距离屏幕左边的距离
- screenY:事件发生时鼠标距离屏幕上方的距离
修改键:
- 有时我们会结合键盘和鼠标来修改鼠标事件,这时就要使用类似Shift、Ctrl、Alt和Meta之类的修改键了,有4个表示这些修改键状态的属性:
- shiftKey
- ctrlKey
- altKey
- metaKey
- 有时我们会结合键盘和鼠标来修改鼠标事件,这时就要使用类似Shift、Ctrl、Alt和Meta之类的修改键了,有4个表示这些修改键状态的属性:
mousewheel事件触发后,会冒泡到document或者window,此外,该事件对应的事件对象中有一个wheelDelta属性,当滑轮向上滚是,该属性值是120的倍数;向下滚时,该属性值是-120的倍数.
FF(fireFox)还支持一个DOMMouseScroll事件,与mousewheel类似,只不过该事件的信息存放在event.detail(Opera也是)中,属性值为-3的倍数时,为滑轮向前滚;为3的倍数时,为滑轮向后滚。
为避免篇幅过长,其它事件在下一篇博客进行介绍。