Javascript 和 HTML 之间的交互是通过 事件 来实现的。最早在 IE 中出现,被作为分担服务器端运算负载的一种手段。到现在,几乎所有的浏览器都支持事件处理。在 DOM2 级中得到规范。
事件流
事件流 描述的是从页面中接受事件的顺序。IE 和 Netscape 提出了完全相反的事件流概念。
事件冒泡: IE 中的事件流叫做 事件冒泡 ,即从最具体的元素逐级向外传播到较不具体的元素。(所有现代浏览器都支持事件冒泡)
事件捕获: Netscape 提出了另一种事件流叫做 事件捕获 。他们的思想是最具体的元素应该最后接受到事件,所以事件捕获是 “从外向内” 传播的。
DOM事件流: “DOM2级事件”规定了事件流包括三个阶段:首先发生事件捕获,然后是实际的目标接受到事件,最后一个阶段是事件冒泡。
汇总: IE8及更早的版本不支持 DOM2 级事件流。
事件处理程序
事件就是用户或浏览器自身执行的某种动作。像click
、load
等都是事件的名字,而响应这个事件的函数就叫做 事件处理程序 。事件处理程序以 on
开头。Javascript 有三种事件模型:内联模型 、 脚本模型 和 DOM2级模型 。
内链模型: 被淘汰的方式,举个例子:
脚本模型: 这个是现在用的最多的一种方式:
DOM2级模型
“DOM2级事件”定义了两个方法:(可用于所有 DOM 节点)
- addEventListener() 添加事件
- removeEventListener() 移除事件
这两个方法都接受三个参数:要处理的事件名(click
、mouseover
)、事件处理程序(一个匿名函数) 和 一个布尔值(最后一个布尔值如果是 true 表示在捕获阶段执行事件,如果是 false 表示在冒泡阶段执行事件。)
PS: 大多数情况下,都将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度兼容不同的浏览器。
|
|
DOM2方式的特点:
1、可以为同一个元素添加多个事件处理程序,他们会按照顺序依次执行。
2、移除事件貌似麻烦了很多。
|
|
IE中的事件处理程序
IE 实现了与 DOM 中类似的两个方法:
- attachEvent() 添加事件
- detachEvent() 移除事件
这两个方法接受两个参数:事件处理程序的名称(onclick
、onmouseover
) 和 事件处理函数(一个匿名函数)。(IE 默认使用冒泡方式)
需要注意的是它 DOM2 中两个方法的区别:
区别一: 第一个参数是 onclick ,而不是 click 。
区别二: 事件处理程序会在全局作用于下运行,里面的 this 指的是 window
。(在做跨浏览器是这一点要特别注意)
|
|
优缺点:
优点:同样可以添加多个事件处理程序。但是,这些事件是按添加的相反顺序执行。
缺点:和上面一样,使用匿名函数是不能被移除。需要传入对相同函数的引用。
跨浏览器事件处理程序
我们要创建一个方法,视情况分别使用 传统模型、DOM2级模型 或者 IE 事件处理程序。
这个方法接受三个参数:要操作的元素、事件类型 和 事件处理函数。
事件对象
在触发 DOM 上的某个事件时,会产生一个事件对象 event
,这个对象中包含着所有与事件有关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息。例如鼠标操作导致的事件对象中,包含鼠标位置的信息,键盘操作导致的事件对象中,包含与按键有关的信息。所有浏览器都支持 event
对象,不过支持的方式不同。
W3C中的事件对象
无论指定事件处理程序时使用什么方法(DOM0级、DOM2级等),都会传入 event
对象。
event 对象的属性和方法: (这里之列举最常用的)
属性/方法 | 说明 |
---|---|
target | 事件的目标 |
type | 被触发的事件类型 |
currentTarget | 其事件处理程序当前正在处理事件的那个元素 |
cancelable | 表明是否可以取消当前事件的默认行为 |
preventDefault() | 取消时间的默认行为。如果 cancelable 是 true 就可以使用这个方法 |
bubbles | 表明事件是否冒泡 |
stopPropagation() | 取消时间的进一步捕获或冒泡。如果 bubbles 为 true 则可以使用这个方法 |
注意:
1、在事件执行内部, this
始终等于 currentTarget
。而 target
只包含事件的实际目标。也就是说 this
和 currentTarget
返回的是你为事件指定的目标元素,而 target
是真正触发这个事件的目标。
2、只有 cancelable
的值为 true
的事件,才可以使用 preventDefault()
来取消器默认行为。
3、stopPropagation() 方法用于立即停止事件冒泡或捕获。
IE中的事件对象
与访问 W3C 中的 event 对象不同,IE 中的 event
对象的访问 取决于指定事件处理程序的方法。
脚本模式: event 作为 window
对象的一个属性存在
DOM2级: event
作为一个参数被传入事件处理程序。
IE 中的 event 对象的属性和方法:
属性/方法 | 说明 |
---|---|
cancelBubble | 默认值为 false,将其设置为 true 时可以取消事件冒泡(相当于 DOM 中的 stopPropagation() 方法) |
returnValue | 默认值为 true,将其设置为 false 是可以取消时间的默认行为(相当于 DOM 中的 preventDefault() 方法) |
srcElement | 事件的目标(和 DOM 中的 target 一样) |
type | 被触发事件的类型 |
注意:
1、因为事件处理程序的 作用域 是由指定的方式决定的,所以要特别注意
2、只要将 returnValue 属性的值设置为 false 就可以阻止事件的默认行为
3、cancelBubble 属性用来停止事件的冒泡(IE不支持事件捕获)这里就不举例了。
跨浏览器的事件对象
这里有4个方法:
常用事件类型汇总
常用的事件类型和具体用法你都可以在这里找到:HTML DOM 事件对象
自己介绍一下 鼠标事件 和 键盘事件
鼠标事件
当浏览器执行鼠标事件的时候回以函数的形式返回一个 event 对象
event对象有一个 button 属相,按下鼠标的不同按键会返回不同的值(貌似很有用)
键盘事件
键盘事件一共有三种:
keydown 键盘按下是执行
keyup 键盘松开是执行
keypress 只支持字符键(能打印出字符的键,不包括enter、shift、Ctrl等)
这里理解一个概念
键码: 键盘上每个键都会对应一个数字,这个数字就称为键码。(字符的键码就是其对应的ASICC编码(字母的话按小写来),非字符也会有一个对应的值)。怎么获得这个键码呢??用到event对象的另一个属性 keyCode
如果使用keypress方法来返回keyCode呢?
注意:键码在不同浏览器上可能会有所不同(比如 ; 分号,,可以自己试一下)。那么怎么做到兼容呢??再来认识一个概念:
字符编码: 这个是唯一的
如果只用到字符的事件就用 keypress 的 charCode方法
事件委托
由于事件处理程序可以为现代 WEB 应用程序提供交互能力,因此许多开发人员会不分青红皂白地想页面中添加大量的处理程序。这样做会导致什么问题呢?首先,每个函数都是对象,都会占用内存;其次,必须事件指定好所有事件处理程序而导致 DOM 访问次数过多,延迟整个页面的交互就绪时间。
对“事件处理程序过多”问题的解决方案就是 事件委托 。事件委托利用 事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
举个例子: 下面是三个不同的按钮。
我们要为他们指定 click
事件,传统意义上我们会分别为他们指定事件,就像下面这样做:
在来看看用 事件委托 应该怎么做:
对比就会发现这种方式的优势,首先,我们只指定了一个事件就完成了为三个按钮添加事件的功能,较少了程序运行所需的内存;另外,只有一次 DOM 操作,这使得交互会很快就绪。是不是很完美。
适合采用 事件委托 的事件包括 click
、mousedown
、mouseup
、keydown
、keyup
和 keypress
。(必须支持事件冒泡)