前言
事件是JavaScript最鲜明的特性,JavaScript以事件驱动实现页面交互,当事件发生时,浏览器会自动调用事件处理函数,同时生成事件对象,传递给事件处理函数。
【学习要点】
- 了解事件模型、事件流、事件类型
- 能够正确注册事件、销毁事件
- 能够自定义事件
1 事件基础
1.1 事件流
事件流是多个节点对同一种事件进行响应的先后顺序,主要包括:
1、冒泡型
2、捕获型
3、混合型(支持冒泡型和捕获型两种事件流)
根据事件流类型,可把事件传播的整个过程分为3个阶段:
-
捕获阶段
事件从document对象沿着文档树向下传播到目标节点,如果目标节点的任何一个上级节点注册了相同事件,那么事件在传播过程中就会首先在最接近顶部的上级节点执行,依次向下传播。
-
目标阶段
注册在目节点上的事件被执行
-
冒泡阶段
事件从目标节点向上触发,若上级节点注册了相同事件,将会逐级响应,依次向上传播。
1.2 事件类型
根据触发对象不同,可将浏览器中发生的事件分成不同类型:
-
UI事件
UI事件中主要包括load,unload,abort,error,select,resize,scroll事件。
-
焦点事件
blur 在元素失去焦点时触发。这个事件不冒泡,所有浏览器都支持。
focus 在元素获得焦点时触发。这个事件不冒泡,所有浏览器都支持。
focusin 在元素获得焦点时触发。这个事件冒泡,某些浏览器不支持。
focusout 在元素失去焦点时触发。这个事件冒泡,某些浏览器不支持。
注意:即使blur和focus不冒泡,也可以在捕获阶段侦听到他们。 -
鼠标与滚轮事件
click—用户单击鼠标左键或按下回车键触发。
dbclick—用户双击鼠标左键触发。
mousedown—在用户按下了任意鼠标按钮时触发。
mouseenter—在鼠标光标从元素外部首次移动到元素范围内时触发。此事件不冒泡。
mouseleave—元素上方的光标移动到元素范围之外时触发。不冒泡。
mousemove—光标在元素的内部不断的移动时触发。
mouseover—鼠标指针位于一个元素外部,然后用户将首次移动到另一个元素边界之内时触发。
mouseout—用户将光标从一个元素上方移动到另一个元素时触发。
mouseup—在用户释放鼠标按钮时触发。
【注意】:上述所有事件除了mouseenter和mouseleave外都冒泡。
重要:只有在同一个元素上相继触发mousedown和mouseup事件,才会触发click事件。同样,只有在同一个元素上触发两次click事件,才会触发dbclick事件。
-
键盘与文本事件
keydown:当用户按下键盘上的任意键时触发。按住不放,会重复触发。
keypress:当用户按下键盘上的字符键时触发。按住不放,会重复触发。
keyup:当用户释放键盘上的键时触发。
textInput:这是唯一的文本事件,用意是将文本显示给用户之前更容易拦截文本。
这几个事件在用户通过文本框输入文本时才经常用到。 -
合成事件
-
变动事件:当底层DOM结构发生变化时触发
-
HTML5事件
-
设备事件
-
触摸与手势事件
1.3 绑定事件
-
静态绑定
<button οnclick="alert('静态绑定')">按钮</button>
-
动态绑定
<button id="btn"></button> var button=document.getElementById('btn'); button.onclick=function(){ alert('动态绑定'); };
动态绑定可以在脚本中直接为页面元素附加事件,不用破坏HTML结构,比静态绑定灵活。
1.4 定义事件处理函数
自定义函数实现事件处理,由事件触发进行调用。
1.5 注册事件
(一)在DOM事件模型中,通过调用对象的addEventListener()
方法注册事件。用法如下:
element.addEventListener(String type,Function listener,bollean useCapture)
-
type:注册事件的类项名。
事件类型与事件属性不同,事件类型名没有on前缀。如对于事件属性onclick,它对应的事件类型为click。
-
listener:监听函数,即事件处理函数。
在指定类型的事件发生时将调用该函数。调用该函数时,默认传递给它的唯一参数是event对象。
-
useCapture:是一个布尔值。
若为true,则表明指定的事件处理函数将在事件传播的捕获阶段触发;若为false,表明在冒泡阶段触发。
(二)IE事件模型使用 attachEvent() 方法注册事件,用法如下:
element.attachEvent(etype,eventName)
- etype:设置事件类型,如onclick、onkeyup、onmousemove等。
- eventName:设置事件名称,即事件处理函数。
1.6 销毁事件
(一)DOM事件模型中
element.removeEventListener(String type,Function listener,bollean useCapture)
参数说明同 addEventListener。
removeEventListener()方法只能删除 addEventListener()方法注册的事件。
(二)IE事件模型中
element.detachEvent(etype,eventName)
参数说明同attachEvent。
【补】手撕原生js实现事件绑定和事件解绑函数
绑定:
var target=document.getElementById('target');
function addEvents(target,type,func){
if(target.addEventListener){
target.addEventListener(type,func,false);
}else if(target.attachEvent){
target.attachEvent('on'+type,func);
}else{
target['on'+type]=func;
}
}
解绑:
function removeEvents(target,type,func){
if(target.removeEventListener){
target.removeEventListener(type,func,false);
}else if(target.detachEvent){
target.detachEvent('on'+type,func);
}else{
target['on'+type]=null;
}
}
1.7 使用event
DOM事件模型中event对象属性:(IE事件模型不支持这些方法)
属性 | 说明 |
---|---|
bubbles | 指示事件是否是冒泡类型,返回布尔值 |
cancelable | 指示事件是否可以取消的默认动作,返回布尔值 |
currentTarget | 返回触发事件的当前节点,即当前处理改事件的元素、文档或窗口 |
eventPhase | 返回事件传播的当前阶段,包括捕获阶段(1)、目标阶段(2)、冒泡阶段(3) |
target | 返回事件的目标节点(触发改事件的节点) |
timeStamp | 返回事件生成的日期和时间 |
type | 返回当前event对象表示的事件名称,如‘submit’、‘load’或‘click’ |
DOM事件模型中event对象方法:
方法 | 说明 |
---|---|
initEvent() | 初始化新建的event对象的属性 |
preventDefault() | 通知浏览器不要执行与事件关联的默认动作 |
stopPrapagation() | 终止事件在传播过程中的捕获、目标处理或冒泡阶段进一步传播 |
1.8 事件委托
事件委托(delegate),也称事件托管或事件代理,就是把目标节点的事件绑定到祖先节点上。
这种简单而优雅的时间注册方式是因为:事件传播过程中,逐层冒泡总能被祖先节点捕获。
事件委托的优势:优化代码,提升运行性能,真正把HTML和JavaScript分离,也能防止在动态添加或删除节点过程中注册的事件丢失现象。