事件是文档或者浏览器窗口中发生的,特定的交互瞬间。事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字。事件是javaScript和DOM之间交互的桥梁。你若触发,我便执行——事件发生,调用它的处理函数执行相应的JavaScript代码给出响应。典型的例子有:页面加载完毕触发load事件;用户单击元素,触发click事件。
事件流
事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。有两种事件流模型。
冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。即从DOM树的叶子到根。(推荐)
捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。即从DOM树的根到叶子。
DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先是事件捕获,为截获事件提供了机会,这个时候实际的目标不会接收到事件。然后是实际的目标接收到事件,并在事件处理中被看成冒泡阶段的一部分。最后一个阶段是冒泡阶段,可以在这个阶段对事件作出相应。
尽管“DOM2级事件”标准规范明确规定事件捕获阶段 不会涉及事件目标 ,但是在IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都会在捕获阶段触发事件对象上的事件。 结果,就是有两次机会在目标对象上面操作事件。事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字。响应某个事件的函数就叫事件处理程序(或事件侦听器)。事件处理程序的名字以"on"开头,因此click事件的事件处理程序就是onclick,load事件的事件处理程序就是onload。为事件指定事件处理程序的方式有好多种。
HTML事件处理程序
事件直接加在html元素上。这种方式也有两种方法,都很简单:
第一种:直接在html中定义事件处理程序及包含的动作。onclick="alert('clicked!')"
第二种:html中定义事件处理程序,执行的动作则调用其他地方定义的脚本。onclick="showMessage()"
通过event变量可以直接访问事件对象,比如οnclick="alert(event.type)"会弹出click事件。在函数内部,this值等于事件的目标元素。这种方式有个明显的缺点,就是HTML与JavaScript代码紧密耦合,如果要更换事件处理程序,就要改动两个地方:HTML代码和JavaScript代码。
DOM0级事件处理程序
把一个函数赋值给一个事件处理程序属性。如:myBtn.onclick=function(){alert("clicked!");}
这种方法简单而且跨浏览器,但是只能为一个元素添加一个事件处理函数。因为这种方法为元素添加多个事件处理函数,则后面的会覆盖前面的。使用DOM0级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中运行的,换句话说,程序中的this引用当前元素。
删除事件处理程序:myBtn.οnclick=null;
DOM2级事件处理程序
DOM2级事件定义了两个方法用于添加和删除事件处理程序:addEventListener()和removeEventListener()。所有的DOM节点都包含这2个方法。这两个方法都需要3个参数:事件名,事件处理函数,布尔值。这个布尔值为true,在捕获阶段处理事件,为false,在冒泡阶段处理事件,默认为false。使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序,而且按照添加的顺序触发。
删除事件处理程序:通过addEventListener添加的事件处理程序必须通过removeEventListener删除,且参数一致。所以通过addEventListener添加的匿名函数将无法删除。
大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。
IE事件处理程序
IE8及以下版本浏览器实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法都需要两个参数:事件处理程序名称和事件处理程序函数。由于IE8及更早版本只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。注意是事件处理程序名称而不是事件名称,所以要加上on,是onclick而不是click。
IE事件处理程序中还有一个地方需要注意:作用域。使用attachEvent()方法,事件处理程序会在全局作用域中运行,因此this等于window。而dom2或dom0级的方法作用域都是在元素内部,this值为目标元素。
当添加多个不同的事件处理程序时,与DOM方法不同的是,这些事件处理程序不是以添加它们的顺序执行,而是以相反的顺序被触发。
删除事件处理程序:通过attachEvent添加的事件处理程序必须通过detachEvent方法删除,且参数一致。
和DOM事件一样,添加的匿名函数将无法删除。
由于这些差异,为了更好的开发,开发人员可以编写跨浏览器的事件处理程序或使用隔离浏览器差异的JavaScript库。
事件对象
在触发DOM上的某个事件时,会产生一个事件对象event,该对象包含着所有与事件有关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息。例如:鼠标操作产生的event中会包含鼠标位置的信息;键盘操作产生的event中会包含与按下的键有关的信息。所有浏览器都支持event对象,但支持方式不同,在DOM中event对象必须作为唯一的参数传给事件处理函数,在IE中event是window对象的一个属性。
DOM中的事件对象
兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0级或DOM2级),都会传入event对象。
在通过HTML特性指定事件处理程序时,变量event中保存着event对象。如:<input type="button" value="click" onclick="alert(event.type)"/>
DOM0级和DOM2级事件处理程序都会把event作为参数传入。
DOM中事件对象重要的属性:type:被触发的事件的类型;target:事件的目标。
DOM中事件对象重要的方法:preventDefault():阻止特定事件的默认行为;stopPropagation():阻止事件冒泡。
事件对象的eventPhase属性,可以用来确定事件当前正位于事件流的那个阶段。如果是在捕获阶段调用的事件处理程序,那么eventPhase等于1;如果事件处理程序处于目标对象上,则eventPhase等于2;如果是在冒泡阶段调用的事件处理程序,eventPhase等于3.这里要注意的是,尽管“处于目标”发生在冒泡阶段,但eventPhase任然一直等于2。
只有在事件处理程序执行期间,event对象才会存在;一旦事件处理程序执行完成,event对象就会被销毁。
IE中的事件对象
在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在。如果事件处理程序是使用
attachEvent()添加的,那么就会有一个event对象作为参数被传入事件处理程序函数中。如果是通过HTML特性指定的事件处理程序,那么还可以通过一个名叫event的变量来访问event对象(与DOM中的事件模型相同)。
IE中事件对象重要的属性:type:被触发的事件的类型;srcElement:事件的目标(与DOM中的target属性相同);cancelBubble:与DOM中的stopPropagation()方法作用相同,都是用来停止事件冒泡的,设置为true即可;returnValue:与DOM中的preventDefault()方法相同,用于阻止特定事件的默认行为,设置为false即可。
虽然DOM与IE中的event对象不同,看基于它们之间的相似性依旧可以拿出跨浏览器的方案。
事件类型
web浏览器中可能发生事件有很多类型。如前所诉,不同的事件类型具有不同的信息,而“DOM3级事件”规定了以下几类事件:UI事件、焦点事件、鼠标事件、滚轮事件、文本事件、键盘事件、合成事件、变动事件和变动名称事件。除了这几类事件之外,HTML5也定义了一组事件,而有些浏览器还会在DOM和BOM中实现其他专有事件。这些专有事件一般都是根据开发人员需求定制的,没有什么规范,因此不同浏览器的实现有可能不一致。
DOM3级事件模块在DOM2级事件模块基础上重新定义了这些事件,也添加了一些新事件。包括IE9在内的所有主浏览器都支持DOM2级事件。IE9支持DOM3级事件。
UI事件
UI事件指的是那些不一定与用户操作有关的事件。UI事件中主要包括load,unload,abort,error,select,resize,scroll事件。
- blur 在元素失去焦点时触发。这个事件不冒泡,所有浏览器都支持。
- focus 在元素获得焦点时触发。这个事件不冒泡,所有浏览器都支持。
- focusin 在元素获得焦点时触发。这个事件冒泡,某些浏览器不支持。
- focusout 在元素失去焦点时触发。这个事件冒泡,某些浏览器不支持。
注意:即使blur和focus不冒泡,也可以在捕获阶段侦听到他们。
- click---用户单击鼠标左键或按下回车键触发
- dbclick---用户双击鼠标左键触发。
- mousedown---在用户按下了任意鼠标按钮时触发。
- mouseenter---在鼠标光标从元素外部首次移动到元素范围内时触发。此事件不冒泡。
- mouseleave---元素上方的光标移动到元素范围之外时触发。不冒泡。
- mousemove---光标在元素的内部不断的移动时触发。
- mouseover---鼠标指针位于一个元素外部,然后用户将首次移动到另一个元素边界之内时触发。
- mouseout---用户将光标从一个元素上方移动到另一个元素时触发。
- mouseup---在用户释放鼠标按钮时触发。