本文内容:
- 理解事件流
- 使用事件处理程序
- 不同的事件类型
基本概念:javaScript与HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察员模式的模型,支持页面的行为(JavaScript)与页面的外观(HTML和CSS代码)之间的松散耦合。
1.事件流
事件流分为两种:IE的冒泡流 Nercape Communicator的事件捕获流
1.1 事件冒泡
IE的事件流叫做事件冒泡,即事件开始时有最具体的元素(文档中嵌套层次最深的那个节点)接受,然后逐级向上传播到较为不具体的节点(文档)。
例如:
<!DOCTYPE html>
<html>
<head>
<title>Event Bubbling Example</title>
</head>
<body>
<div id='myDiv'>Click Me</div>
</body>
</html>复制代码
如果你单击了页面中的<div>元素,那么这个click事件会按照如下顺序传播:
- <div>
- <body>
- <html>
- document
也就是说,click事件首先在<div>元素上发生,而这个元素就是我们单击的元素。然后,click事件沿DOM树向上传播,在每一级节点上都会发生,直至传播到document对象。
1.2 事件捕获
Nercape Communicator踢出的另一种事件流叫做事件捕获。
事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于事件到达预定目标之前捕获它。
如果以之前代码作为例子,那么元素就会以下面的顺序触发click事件
- document
- <html>
- <body>
- <div>
在事件捕获的过程中,document对象首先接收到click事件,然后事件沿DOM树依次向下,一直传播到事件的实际目标,即<div>元素。
由于老版本的浏览器不支持,所以很少使用事件捕获,所以只有在特殊需要时再使用事件捕获。
1.3 DOM事件流
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段
首先发生的是事件捕获,为截获事件提供了机会。
然后是实际的目标接收到事件。
最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。
在DOM事件流中,实际的目标(div元素)在捕获阶段不会接收到事件。这意味着在捕获阶段,事件从document到<html>再到<body>后就停止了。下一个阶段是“处于目标”阶段,于是事件在div上发生,并在事件处理中被看成冒泡阶段的一部分。
多数支持DOM事件流的浏览器都实现了一种特定的行为;即使'DOM2级事件'规范明确要求捕获阶段不会涉及事件目标,但IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都会在捕获阶段触发事件对象上的事件。结果就是有两个机会在目标对象上操作事件。
IE9、Safari、Chrome、Firefox和Opera9.5都支持DOM时间流;IE8及更早版本不支持DOM事件流
2. 事件处理程序
事件就是用户或浏览器自身执行的某种动作。click、load和mouseover,都是事件的名字。而相应某个事件的函数就叫做事件处理程序(或事件侦听器)。
2.1 HTML事件处理程序
某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的HTML特性来制定。这个特性的值应该是能够执行的JavaScript代码。
例如,要在按钮被单击时执行一些JavaScript,可以像下面这样编写代码:
<input type='button' value='Click Me' onclick='alert("Clicked")'/>复制代码
事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码。
在HTML中定义的事件处理程序可以包含要执行的具体动作,也可以调用在页面其他地方定义的脚本,如下面的例子所示:
<script type='text/javascript'>
function showMessage(){
alert('hello world');
}
</script>
<input type='button' value='Click Me' onclick='showMessage()' />复制代码
在这个例子中,单间牛牛就会调用showMessage()函数。这个函数实在一个独立<script>元素中定义的,当然也可以被包含在一个外部文件中。这样指定时间处理程序具有一些独到之处。首先,这样会创建一个封装着元素属性值的函数。这个函数中有一个局部变量event,也就是事件对象。
<input type='button' value='Click Me' onclick='alert(event.type)' /> // click
复制代码
通过event变量,可以直接访问事件对象,你不用自己定义它,也不用从函数的参数列表中读取。在这个函数内部,this值等于事件的目标元素,例如:
<input type='button' value='Click Me' onclick='alert(this.value)' /> //Click Me复制代码
html中指定事件处理程序有两个缺点。
首先,存在一个时差问题,如果某个事件处理程序一加载就触发,而页面还不具备执行条件的话,就会引发错误,因此很多HTML事件处理程序都会被封装在一个try-catch块中,以便错误不会浮出水面。
另一个缺点是,这样扩展事件处理程序的作用于连在不同浏览器中会导致不同结果。不同JavaScript引擎遵循的标识符解析规则略有差异,很可能会在访问非限定对象成员时出错。
因为HTML指定事件处理程序时HTML与JavaScript代码紧密耦合,所以一般我们都选择使用JavaScript指定事件处理程序。
2.2 DOM0级事件处理程序
使用DOM0级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序实在元素的作用域中进行;换句话说,程序中的this引用当前元素。
要删除DOM0级事件处理程序的方法也简单:
btn.onclick = null复制代码
2.3 DOM2级事件处理程序
“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:
addEventListener() 和 removeEventListener()。
所有DOM节点中都包含这两个方法,并且他们都接受3个参数:
要处理的事件名、作为事件处理程序的函数 和 一个布尔值
最后一个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;
如果是false,表示在冒泡阶段调用事件处理程序
使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。这也意味着通过addEventListener()添加的匿名函数(也就是第二个参数)将无法移除。
不建议在事件捕获阶段注册事件处理程序
2.4 IE事件处理程序
IE实现了与DOM中类似的两个方法: attachEvent()和detaEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。IE8只支持事件冒泡,所以attachEvent添加的事件都会被添加到冒泡阶段。
在IE中使用attachEvent时,this 等于 window。
为同一个元素添加多个事件处理程序时,并非以添加的顺序执行,而是以相反的顺序执行。
attachEvent添加的事件可以通过detachEvent来移除,道理跟DOM方法一样。
3.事件对象
在触发DOM上的某个事件时,会唱生一个事件对象event,这个对象中包含这所有与事件有关的信息。包括导致事件的元素,事件的类型以及其他与特定事件相关的信息。例如,鼠标操作导致的事件对象中,会包含鼠标位置的信息,而键盘操作导致的事件对象中,会包含与按下的键有关的信息。所有浏览器都支持event对象,但支持方式不同。
3.1 DOM中的事件对象
兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论指定时间处理程序时使用说明方法,都会传入event对象。
event对象包含与创建它特定事件有关的属性和方法。所有事件都会有下面列出的成员。
属性/方法(只读) 类型 说明
bubbles Boolean 表明事件是否冒泡
cancelable Boolean 表明事件是否可以取消事件的默认行为
currentTarget Element 其事件处理程序当前正在处理事件的那个元素
defaultPrevented Boolean 为true表示已经调用了preventDefault()
detail Integer 与事件相关的细节信息
eventPhase Integer 调用事件处理程序的阶段:1表示捕获,2表示 处于目标,3表示冒泡阶段
PreventDefault Function 取消时间的默认行为。如果cancelable是true,则可以使用这个方法
stopImmediatePropagation() Function 调用事件处理程序的阶段:1表示捕获,2表示 处于目标,3表示冒泡阶段
stopPropagation() Function 取消时间的进一步捕获或冒泡。不过bubbles为 true则可以使用这个方法
target Element 事件的目标
trusted Boolean 为true表示事件是浏览器生成的,为false表示 事件由开发人员通过js创建的
type String 被触发的事件的类型
view AbstractView 与事件关联的抽象视图。等同于发生事件的 window对象
在事件处理程序内部,独享this始终等于CurrentTarget的值,而target则只包含事件的实际目标。如果直接将时间处理程序指定给了目标元素,则this、currentTarget和target包含相同的值。
event.target保存的是触发事件的元素
event.currentTarget和this保存的是绑定事件的元素
HTML5事件
hashchange事件
在URL的参数列表发生变化时通知开发人员。
必须要把hashchange事件处理程序添加给window对象,然后URL参数列表只要变化就会调用它。此时的event对象应该额外包含两个属性:oldURL和newURL。这两个属性分别保存着参数列表变化前后的完整URL。
4.9 触摸与手势事件
touchstart: 当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发。
touchmove:当手指在屏幕上滑动时连续地触发。在这个事件发生期间,调用preventDefault()可以阻止滚动。
touchend:当手指从屏幕上移开时触发
touchcancel:当系统停止跟踪触摸时触发。
每个触摸事件的event对象都提供了在鼠标事件中常见的属性:bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey和metaKey。
除了常见的DOM属性外,触摸事件还包含下列三个用于跟踪触摸的属性。
touches:表示当前跟踪的触摸操作的Touch对象的数组。
targetTouchs: 特定于事件目标的Touch对象的数组。
changeTouches:表示自上次触摸以来发生了什么改变的Touch对象的数组。
每个Touch对象包含下列属性
clientX:触摸目标在视口中的x坐标。
clientY:触摸目标在视口中的y坐标。
identifier:标识触摸的唯一ID。
pageX:触摸目标在页面中的x坐标。
pageY:触摸目标在页面中的y坐标。
screenX:触摸目标在屏幕中的x坐标。
screenY:触摸目标在屏幕中的y坐标。
target:触摸的DOM节点目标。