一文读懂 JavaScript 事件
一、了解JavaScript的三种事件类型
1. 鼠标事件
常见的鼠标事件
事件 | 发生时间 | 触发次数 |
---|---|---|
onclick | 用户单机对象时 | 1次 |
ondbclick | 用户双击对象时 | 1次 |
onmouseover | 鼠标移到某个对象时 | 1次 |
onmouseout | 鼠标移出某个对象时 | 1次 |
onmousemove | 鼠标被移动 | n次 |
onmousedown | 鼠标按键被按下 | 1次 |
onmouseup | 鼠标按键被松开 | 1次 |
2. 键盘事件
常见的键盘事件
事件 | 发生时间 | 触发次数 |
---|---|---|
onkeydown | 键盘按下去触发 | 1次 |
onkeypress | 键盘按下并松开的瞬间触发 | n次 |
onkeyup | 键盘抬起时触发 | 1次 |
a. 常按时触发的事件
当长按一个按键时,会不断触发onkeydown
和onkeypress
,只有按键抬起以后才会触发onkeyup
事件。
b. onkeydown/onkeyup和onkeypress的区别
1)onkeypress
只能捕获字母、数字、符号键,不能捕获功能键(如Enter键、F1~F12键等);onkeydown/onkeyup
基本可以捕获所有功能键(特殊键盘的某些按键除外)。
2)捕获字母键时,onkeypress
可以区分大小写,onkeydown
和onkeyup
不区分大小写。
3)捕获数组键时,onkeydown/onkeyup
可以区分主键盘和小键盘,onkeypress
不能够区分。
c. 通常将键盘事件声明在document上
在使用键盘事件时,通常会直接将键盘事件监测到document上,而且onkeydown
和onkeyup
通常监测一个即可
d. 判断键盘按键
在使用键盘事件时,除了需要检测触发的是onkeydown
还是onkeyup
,更重要的是判断用户按下去的是哪一个按键。
当监测键盘事件时,浏览器会默认将事件因子e传入事件触发函数中,事件因子可以通过keyCode
等属性确认按键ASCⅡ码值,进而确定用户按下的是哪一个按键。
兼容方式取到按键ASCⅡ编码
var code=evn.keyCode‖evn.whi‖evn.charCode;
常用的ASCⅡ码值参照表
ASCⅡ码值 | 按键或含义 |
---|---|
0 | 空字符(Null) |
13 | Enter 键 |
27 | Esc 键 |
32 | 空格键 |
48-57 | 数字键0-9 |
65-90 | 大写字母A-Z |
97-122 | 小写字母a-z |
127 | Delete 键 |
3. HTML事件
常见的HTML事件
事件 | 发生时间 |
---|---|
onload | 文档或图像加载后 |
onunload | 文档卸载后,或者退出页面时 |
onblur | 元素失去焦点 |
onselect | 文本被选中 |
oninput | 元素获得焦点时 |
onchange | 内容被改变 |
onfocus | 元素获得焦点时 |
onsubmit | 表单提交时 |
onreset | 重置按钮被单击 |
onresize | 窗口重新调整大小时 |
onscroll | 当文档被滚动时发生的事件 |
ondrag | 当元素正在拖动时触发的事件 |
ondragstart | 当元素开始被拖动的时候触发的事件 |
ondragover | 元素被拖动到指定区域的时候触发的事件 |
ondrop | 当放置被拖动元素时触发的事件 |
4. event事件因子
取到事件因子有两种方式,除了键盘事件,还可以在任何事件的触发函数中使用window.event
取到事件因子对象。
element.onclick = function(e){
var evn = e || window.event;
}
event对象属性
属性名 | 说明 |
---|---|
keyCode | 检查键盘事件相对应的Unicode 字符码 |
srcElement | 返回触发事件的元素 |
target | 返回触发事件的元素(对象) |
type | 返回当前 event 对象表示的事件名称 |
button | 检查按下的鼠标键 |
x,y | 返回鼠标相对于 css 属性中有 position 属性的上级元素的 x 和 y 坐标 |
clientX,clientY | 返回鼠标在浏览器窗口区域的 x 和 y 坐标 |
screenX,screenY | 返回鼠标相对于用户屏幕中的 x 和 y 坐标 |
altKey | 检查 Alt 键的状态。当 Alt 键按下时,值为 True;否则为 False |
ctrlKey | 检查 Ctr 键的状态。当 Ctr 键按下时,值为 True;否则为 False |
shiftKey | 检查 Shift 键的状态。当 Shift 键按下时,值为 True;否则为 False |
toElement | 检测 onmouseover 和 onmouseout 事件发生时,鼠标所进入的元素 |
fromElement | 检测 onmouseover 和 onmouseout 事件发生时,鼠标所离开的元素 |
注意:检测鼠标按键的button属性仅用于onmousedown
、onmouseup
和onmousemove
事件。对于其他事件,不管鼠标状态如何,都返回0(比如onclick
)。它有8个属性值,分别是0没按键、1按左键、2按右键、3按左右键、4按中间键、5按左键和中间键、6按右键和中间键、7按所有的键。
e.target和this的区别
属性 | 返回值 |
---|---|
e.target | 返回的是触发事件的对象(元素) |
this | 返回的是绑定/调用事件的对象(元素) |
二、掌握JavaScript的两种事件模型
1. DOM0 事件模型
DOM0 模型有两种绑定事件的方式,分别是内联模型和脚本模型。
a. 内联模型
内联模型又称为“行内绑定”,其绑定事件的方式是直接将函数名作为 HTML 标签某个事件的属性值。
基本语法如下:<button onclick="func( )">按钮</button>
缺点:违反 W3C 关于 HTML 与 JavaScript 分离的基本原则。
b. 脚本模型
脚本模型又称为“动态绑定”,其绑定的方式是通过在 JavaScript 中选中一个节点,并给节点的 onlick
事件添加监听函数。
基本语法如下:window.onload = function(){} || document.getElementById("div").onclick = function(){}
- 优点:实现了 HTML 与 JavaScript 分离,符合 W3C 的基本原则。
- 缺点:
-
- 1)同一节点只能绑定一个同类型事件,如果绑定多次,则只有最后一次生效
-
- 2)一旦绑定事件,无法取消事件绑定。
2. DOM2 事件模型
DOM0绑定事件的两种方式都有其局限性。为了解决DOM0事件模型所存在的局限性,DOM2事件模型应运而生。
添加事件绑定
DOM2 事件模型的绑定相对于 DOM0 要稍微复杂一些,并且针对浏览器版本的不同,有两种不同的绑定方式。
1)针对IE8之前的浏览器,使用attachEvent()
进行事件绑定。
基本语法如下:
var btn = document.getElementById("btn");
btn.attachEvent("onclick",function(){
// onclick 触发时执行的回调函数
});
其中,attachEvent()
接收两个参数。
① 第一个参数是触发的事件类型,主要事件名称需要用“on”开头。
② 第二个参数是触发事件时执行的回调函数。
2)除 IE8 之外的其他浏览器,统一使用 W3C 规范,使用addEventListener()
进行事件绑定。
基本语法如下:
var btn = document.getElementById("btn");
btn.addEventListener("click",function(){
// click 触发时执行的回调函数
}, true/false);
其中,addEventListener()
接收3个参数。
① 第一个参数是触发的事件类型,主要事件名称不需要用“on”开头。
② 第二个参数是触发事件时执行的回调函数。
③ 第三个参数是模型参数,表示事件冒泡或事件捕获,false(默认)
表示事件冒泡,true表示事件捕获。
取消事件绑定
DOM2 和 DOM0 相比有一个非常重要的区别,就是使用 DOM2 绑定的事件可以取消事件绑定。如果要取消事件绑定,那么在绑定事件时,回调函数必须使用有名函数,而不能使用匿名函数。
基本语法如下:
var btn = document.getElementById("btn");
btn.attachEvent("onclick",clickFunction(){
});
btn.addEventListener("click",clickFunction(){
}, true/false);
function clickFunction(){
// 单击事件的回调函数
}
为什么绑定的时候不能使用匿名函数作为回调函数呢?主要原因在于取消事件绑定的时候,语法要求必须传入需要取消的函数名。而匿名函数没有函数名,故无法取消。针对不同浏览器,取消事件绑定也有两种不同方式。
1)针对IE8之前使用attachEvent()
绑定的事件,可以使用detachEvent()
取消事件绑定。
基本语法如下:btn.detachEvent("onclick",函数名);
2)针对其他浏览器使用addEventListener()
绑定的事件,可以使用removeEventListener()
取消事件绑定。
基本语法如下:.removeEventListener("click",函数名);
三、掌握JavaScript的事件流模型
1. 事件冒泡
当某 DOM 元素触发某事件时,会从当前 DOM 元素开始,逐个触发其祖先元素的同类型事件,直到 DOM 根节点。
2. 事件捕获
当某 DOM 元素触发某事件时,会从根节点开始,逐个触发其祖先元素的同类型事件,直到当前节点。
3. 事件委派
事件委派也叫事件委托,是将本该添加在节点自身的事件,选择添加到其父节点上,同时委派给当前元素来执行。
a. 事件委派的原理
事件委派的原理就是事件冒泡。由于给多个子元素添加事件,会沿着事件冒泡流触发其父元素的同类型事件,所以可以直接将事件添加在父元素上,并在事件函数中判断单击的是哪一个子元素,进而进行具体操作。
b. 事件委派的作用
事件委派有很大用处,主要体现在如下两点:
(1)提高性能将事件绑定在父节点上,只需要绑定一个事件就可以;而将事件依次添加给子节点,则需要绑定多个事件。因此,事件委派具有更优的性能。
(2)新添加的元素会具有同类型元素的事件如果使用其他方式绑定事件,当页面新增同类的节点时,这些节点不会获得之前绑定的事件。但是,使用事件委派可以让新添加的元素获得之前绑定的事件。
4. 阻止冒泡事件
事件委派的原理就是事件冒泡,但并不是所有的事件冒泡都是对开发有利的,实际开发中,大多情况并不想让子元素的事件影响到父元素。
- 对于 IE8 以前的浏览器,可以将
e.cancelBubble
属性设为true
; - 对于其他浏览器,则可以调用
e.stopPropagation()
方法。
5. 阻止默认事件
除了事件冒泡,还有一种情况存在妨碍开发的问题,那就是某些标签的默认事件。比如,a
标签自带跳转页面功能,submit
标签自带提交表单功能,reset
标签自带清除表单功能……这些功能在需要的情况下,都是人们的得力助手。但是,不需要的时候,它们就会影响功能的实现效果。这时候就需要选择取消 HTML 标签的默认事件。
取消默认事件也有两种常用方式。
- 对于 IE8 之前的浏览器,可以将
e.returnValue
属性设为false
; - 对于 IE8 以外的浏览器,可以调用
e.preventDefault()
方法。