Skip to content

事件

1.事件三要素

事件是有三部分组成,事件源、事件类型、事件处理程序。我们称之为事件三要素

事件源:事件被处罚的对象

js
var btn=document.querySelector('.btn');

事件类型:如何处罚,什么事件,比如鼠标点击(onclick),还是鼠标经过,还是键盘按下

事件处理程序:通过一个函数赋值的方式完成

js
btn.onclick=function(){    
	alert('球芭比母涅牛'); 
}

2.事件类型

2.1 鼠标事件

鼠标事件触发条件
onclick鼠标单击左键触发
ondblclick鼠标双击左键触发
onmouseover鼠标经过触发
onmouseout移出离开触发
onmousedown按下鼠标左键触发
onmouseup松开鼠标左键触发
onmousemove移动鼠标触发
oncontextmenu鼠标右键单击事件

禁止鼠标右键菜单

js
document.addEventListener ('contextmenu', function(e){    
    e.preventDefault () ;
 })

2.2 键盘事件

事件描述
onkeydown键盘按下
onkeyup键盘抬起
onkeypress某个键盘按键被按下时触发 但是它不识别功能键比如ctrl shift箭头等

三个事件的执行顺序是: keydown -- keypress ---keyup

2.3 表单事件

事件描述
oninput表单元素的内容改变时触发
onchange表单元素的内容改变并且失去焦点时触发
onsubmit表单提交时触发
onreset表单被重置后触发
onblur表单失去焦点时触发
onfocus表单获取焦点时触发
onfocusin元素即将获取焦点时触发
onfocusout元素即将失去焦点时触发
onsearch用户向搜索域输入文本时触发
onselect用户选取文本时触发,input、textarea
onsubmit表单提交时触发

2.4 框架/对象事件

事件描述
onabort图像的加载被中断。 ( <object>)
onbeforeunload该事件在即将离开页面(刷新或关闭)时触发
onerror在加载文档或图像时发生错误。 ( <object>, <body><frameset>)
onhashchange该事件在当前 URL 的锚部分发生修改时触发。也就是#后面的内容
onload一张页面或一幅图像完成加载。
onpageshow该事件在用户访问页面时触发
onpagehide该事件在用户离开当前网页跳转到另外一个页面时触发
onresize窗口或框架被重新调整大小。
onscroll当文档被滚动时发生的事件。
onunload用户退出页面。 ( <body><frameset>)

2.5 剪贴板事件

事件描述
oncopy该事件在用户拷贝元素内容时触发
oncut该事件在用户剪切元素内容时触发
onpaste该事件在用户粘贴元素内容时触发

2.6 拖动事件

事件描述
ondrag该事件在元素正在拖动时触发
ondragstart该事件在用户开始拖动元素时触发
ondragend该事件在用户完成元素的拖动时触发
ondragenter该事件在拖动的元素进入放置目标时触发
ondragover该事件在拖动元素在放置目标上移动时触发
ondragleave该事件在拖动元素离开放置目标时触发
ondrop该事件在拖动元素放置在目标区域时触发

在拖放的过程中会触发以下事件:

  • 拖动目标上触发事件(源元素):此时e.target是拖动目标元素
    • ondragstart - 用户开始拖动元素时触发
    • ondrag - 元素正在拖动时触发
    • ondragend - 用户完成元素拖动后触发
  • 释放目标上触发的事件:此时e.target是释放目标元素
    • ondragenter - 当被鼠标拖动的对象进入其容器范围内时触发此事件
    • ondragover - 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
    • ondragleave - 当被鼠标拖动的对象离开其容器范围内时触发此事件
    • ondrop - 在一个拖动过程中,释放鼠标键时触发此事件

2.7 多媒体事件

事件描述
onabort事件在视频/音频(audio/video)终止加载时触发。
oncanplay事件在用户可以开始播放视频/音频(audio/video)时触发。
oncanplaythrough事件在视频/音频(audio/video)可以正常播放且无需停顿和缓冲时触发。
ondurationchange事件在视频/音频(audio/video)的时长发生变化时触发。
onemptied当期播放列表为空时触发
onended事件在视频/音频(audio/video)播放结束时触发。
onerror事件在视频/音频(audio/video)数据加载期间发生错误时触发。
onloadeddata事件在浏览器加载视频/音频(audio/video)当前帧时触发触发。
onloadedmetadata事件在指定视频/音频(audio/video)的元数据加载后触发。
onloadstart事件在浏览器开始寻找指定视频/音频(audio/video)触发。
onpause事件在视频/音频(audio/video)暂停时触发。
onplay事件在视频/音频(audio/video)开始播放时触发。
onplaying事件在视频/音频(audio/video)暂停或者在缓冲后准备重新开始播放时触发。
onprogress事件在浏览器下载指定的视频/音频(audio/video)时触发。
onratechange事件在视频/音频(audio/video)的播放速度发送改变时触发。
onseeked事件在用户重新定位视频/音频(audio/video)的播放位置后触发。
onseeking事件在用户开始重新定位视频/音频(audio/video)时触发。
onstalled事件在浏览器获取媒体数据,但媒体数据不可用时触发。
onsuspend事件在浏览器读取媒体数据中止时触发。
ontimeupdate事件在当前的播放位置发送改变时触发。
onvolumechange事件在音量发生改变时触发。
onwaiting事件在视频由于要播放下一帧而需要缓冲时触发。

2.8 动画事件

事件描述
animationend该事件在 CSS 动画结束播放时触发
animationiteration该事件在 CSS 动画重复播放时触发
animationstart该事件在 CSS 动画开始播放时触发

2.9 过渡事件

事件描述
transitionend该事件在 CSS 完成过渡后触发。

2.10 其他事件

事件描述
onmessage该事件通过或者从对象(WebSocket, Web Worker, Event Source,BroadcastCannel 或者子 frame 或父窗口)接收到消息时触发
onmousewheel已废弃。 使用 onwheel 事件替代
ononline该事件在浏览器由离线变成在线时触发。
onoffline该事件在浏览器由在线变成离线时触发。
onpopstate该事件在窗口的浏览历史(history 对象)发生改变时触发。
onshow该事件当 <menu> 元素在上下文菜单显示时触发
onstorage该事件在 Web Storage(HTML 5 Web 存储)更新时触发
ontoggle该事件在用户打开或关闭 <details> 元素时触发
onwheel该事件在鼠标滚轮在元素上下滚动时触发

3.this

this在函数被调用的过程中,会在函数内部产生,在函数中的this有一个指向

this指向的是函数的调用者,也就是说这个函数由谁来调用,this就指向谁(this就是谁)

this是一个关键字,是在函数被调用(运行)时才会被绑定的,在不同的情况下this的指向是不同的

this的指向

  1. 事件处理函数中 this指向 事件源
  2. 普通函数中 this指向 window
  3. 对象中的方法(函数) this指向 对象本身

4.事件的绑定与移除

4.1 DOM0级事件

  • 同一个节点同一事件只能设置一次,给一个节点绑定多个相同事件会后者覆盖前者
  • 绑定DOM0级事件 语法:元素对象.事件类型 = 事件处理函数

4.1.1 绑定

js
element.onclick = function(){ 
    console.log("事件触发2") 
}

4.1.2 移除

直接赋值为null就行

js
elemeny.onclick = null;

4.2 DOM2级事件(事件监听)

  • 同一个节点同一事件可以绑定多个函数按照绑定顺序执行
  • 绑定DOM2级事件(添加事件监听) 语法:
js
element.addEventListener('click',function(){
    console.log('我是第一个事件');
},false)

4.2.1 主流浏览器绑定

js
元素对象.addEventListener(事件类型,事件处理函数,事件流【捕获/冒泡);

参数

  • 参数1:事件类型传入时不写on,如果使用 onclick 就写 click
  • 参数2:事件处理函数 function(){}
  • 参数3:事件流【捕获/冒泡】 默认值是false表示冒泡,可以不传入 传入true表示捕获

4.2.2 兼容 ie6/7/8绑定

js
元素对象.attachEvent(事件类型,事件处理函数);

参数

  • 参数1:事件类型传入时需要写oin,如果使用 onclick 就写 onclick
  • 参数2:事件处理函数 function(){}
html
<div id="box"></div>

<script>
    var oBox = document.querySelector("#box");            
    // 先触发
    oBox.addEventListener('click',function(){
        console.log('我是第一个事件');
    },false)

    // 后触发
    oBox.addEventListener('click', function(){
        console.log('我是第二个事件');
    },false)
</script>

4.2.3 移除

js
// 主流浏览器支持
元素对象.removeEventListener(事件类型,事件处理函数,事件流【捕获/冒泡】)

// 兼容 ie6\7\8
元素对象.detachEvent(事件类型,事件处理函数);

举例

js
element.removeEventListener("click",fn2,false)

5.事件对象

  • event对象代表事件的状态,跟事件相关的一系列信息的集合。事件对象主要有鼠标事件对象和键盘事件对象
  • 事件对象的产生一定要依赖于 事件的触发 才会 产生

5.1 获取事件对象

  • 针对主流浏览器,事件处理函数的第一个形参就是事件对象

  • 针对ie低版本浏览器,是通过 window对象的event属性实现事件对象的获取

在IE低版本浏览器中(6/7/8)

js
标签对象.事件类型 = function() { 
    console.log(window.event); // 打印事件对象 
}

主流浏览器中

js
标签对象.事件类型 = function(e) { // 不一定要传入 e,ev、event 等均可 
    console.log(e); // 打印事件对象 
}  
// 在事件处理函数中,默认第一个形参就是事件对象

兼容

js
标签对象.事件类型 = function(e) {
    var e = e || window.event; // 通过不同浏览器的方式确定最终的时间对象的使用方式 	
    console.log(e); // 打印事件对象
}

5.2 事件对象通用属性

以下是事件对象常用的属性,通过e.key获取

属性描述DOM
bubbles返回布尔值,指示事件是否是起泡事件类型。2
cancelable返回布尔值,指示事件是否可拥可取消的默认动作。2
currentTarget返回其事件监听器触发该事件的元素。2
eventPhase返回事件传播的当前阶段。2
target返回触发此事件的元素(事件的目标节点)。2
timeStamp返回事件生成的日期和时间。2
type返回当前 Event 对象表示的事件的名称。

5.3 鼠标事件对象

以下是鼠标事件对象常用的属性,通过e.key获取

属性描述
button返回当事件被触发时,哪个鼠标按钮被点击。
0:鼠标左键、1:鼠标中键、2:鼠标又键、
clientX、clientY获取相对于浏览器显示窗口的左边和上边的位置
(不论是否存在滚动条,都是根据浏览器窗口左边和上边计算)
screenX、screenY获取到相对于电脑屏幕的左边和上边的位置。
offsetX、offsetY获取相对于元素边框内左边和上边的位置,不包含边框
pageX、pageY获取相对于整个页面的左边和上边的位置
(不论是否存在滚动条,都是根据页面的左边和上边计算)
relatedTarget返回与事件的目标节点相关的节点。

5.4 键盘事件对象

以下是键盘事件对象常用的属性,通过e.key获取

属性描述DOM
altKey返回当事件被触发时,"ALT" 是否被按下。2
ctrlKey返回当事件被触发时,"CTRL" 键是否被按下。2
Location返回按键在设备上的位置3
charCode返回onkeypress事件触发键值的字母代码。2
key在按下按键时返回按键的标识符。3
keyCode返回onkeypress事件触发的键的值的字符代码,或者 onkeydown 或 onkeyup 事件的键的代码。2
which返回onkeypress事件触发的键的值的字符代码,或者 onkeydown 或 onkeyup 事件的键的代码。2
metaKey返回当事件被触发时,"meta" 键是否被按下。2
relatedTarget返回与事件的目标节点相关的节点。2
shiftKey返回当事件被触发时,"SHIFT" 键是否被按下。2

5.3.1 按键编码keyCode

  1. 我们的键盘上每一个按键都有一个自己独立的编码
  2. 我们就是靠这个编码来确定我们按下的是哪个按键的
  3. 我们通过 event.keyCode或者envent.which来获取
  4. 因为 FireFox2.0不支持keycode所以要用which
  5. 兼容写法var keycode = e.keycode || e.which;
js
document.onkeydown = function(ev){
    var e = ev || window.event;

    // 获取 按键编码的 兼容
    var keycode = e.keycode || e.which;

    console.log(keycode);
    if(keycode === 82){
        obox.style.background = 'red';
    }else if(keycode === 66){
        obox.style.background = 'blue';
    }
}
字母按键键码数字按键键码控制键/功能键键码标点符号键码
A650 (数字键盘)48ESC27`192
B661 (数字键盘)49F1112-189
C672 (数字键盘)50F2113=187
D683 (数字键盘)51F3114[219
E694 (数字键盘)52F4115]221
F705 (数字键盘)53F5116;186
G716 (数字键盘)54F6117'222
H727 (数字键盘)55F7118\220
I738 (数字键盘)56F8119,188
J749 (数字键盘)57F9120.190
K750 (右侧小键盘)96F10121/191
L761 (右侧小键盘)97F11122/ (右侧小键盘)111
M772 (右侧小键盘)98F12123* (右侧小键盘)106
N783 (右侧小键盘)99退格键(Backspace)8- (右侧小键盘)109
O794 (右侧小键盘)100Tab9+ (右侧小键盘)107
P805 (右侧小键盘)101Caps Lock20. (右侧小键盘)110
Q816 (右侧小键盘)102回车键(Enter)13
R827 (右侧小键盘)103Shift16
S838 (右侧小键盘)104Ctrl (Control)17
T849 (右侧小键盘)105Alt18
U85空格键(Space)32
V86Clear12
W87Insert45
X88Delete46
Y89Home36
Z90End35
Page Up33
Page Down34
方向键(←)37
方向键(↑)38
方向键(→)39
方向键(↓)40

5.3.2 组合按键

  1. altKey:alt 键按下得到 true,否则得到 false

  2. shiftKey:shift 键按下得到 true,否则得到 false

  3. ctrlKey:ctrl 键按下得到 true,否则得到 false

  4. 用于设定 组合 按键

  5. ctrl + 其他按键

  6. shift + 其他按键

  7. alt + 其他按键

  8. ctrl + shift + 其他按键

  9. ctrl + alt + 其他按键

  10. ......

  11. 注意 :其他按键只能有一个(也就是除了ctrl、alt、shift的其他案件)

js
document.onkeydown = function(ev){
    var e = ev || window.event;

    // 获取 按键编码的 兼容
    var keycode = e.keycode || e.which;

    if(e.ctrlKey && e.altKey && keycode === 88){
        alert("按键为 ctrl 和 alt 和 X");
    }

}

6.事件流

6.1 概述:

事件流描述的是从页面接收事件顺序。当有层级关系(嵌套关系)的元素,都绑定了相同的事件类型在子元素触发了该事件后,同时也能触发父元素的该事件,这个就是事件流,也可以说是事件的传播

触发条件

  1. 元素之间存在嵌套关系
  2. 父元素和子元素绑定了同类型的事件

事件流的种类:

  1. 事件冒泡、事件捕获

事件流的三个阶段

  1. 捕获阶段:事件从Document节点自上而下向目标节点传播的阶段;

  2. 目标阶段:真正的目标节点正在处理事件的阶段;

  3. 冒泡阶段:事件从目标节点自下而上向Document节点传播的阶段。

6.2 事件冒泡

从具体的向不具体的传播,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素

子元素绑定事件,若父元素绑定同样的事件,就会一级一级往上触发,直到触发到docoment对象上

  • 针对 DOM 0级事件 默认是冒泡,而且只有冒泡,无法改变

  • 针对 DOM 2级事件 默认是冒泡

  • 针对 高版本浏览器 默认是冒泡,但是可以改变

  • DOM 2级事件addEventListener 这个方法的第三个参数决定事件流

    • 默认值为 false,表示 事件冒泡
    • 如果设定值为 true,表示 事件捕获
  • 针对 ie6、7、8低版本浏览器 默认是冒泡,而且只有冒泡,无法改变

6.3 事件捕获

从不具体的向具体的

事件捕获的思想是不太具体的节点应该更早的接收到事件,而最具体的节点应该最后接收到事件

事件捕获只存在于针对高版本浏览器绑定DOM2级事件可以设置

  • 给 addEventListener这个方法的第三个参数决定事件流
  • 传入 true 表示 事件捕获

6.4 阻止事件冒泡

通过事件对象上的属性和方法实现

针对高版本浏览器

  1. event.stopPropagation();

针对 ie6/7/8低版本浏览器

  1. event.cancelBubble = true;

阻止事件冒泡的兼容写法

js
box.onclick = function(ev){
    var e = ev || window.event;
    e.stopPropagation?e.stopPropagation():e.cancelBubble = true;
}

7.事件委托

7.1 什么是事件委托

  1. 所谓的事件委托,就是将要处理的事情委托给别人来完成。
  2. 实现:将子元素的事件委托给父元素绑定

7.2 为什么需要将事件委托

  1. 在工作中,我们经常需要动态增加节点,如果采用传统的绑定事件写法,对于新增的节点事件不会生效

7.3 采用事件委托

  1. 利用事件的事件流机制,点击子元素的时候,也会同步触发父元素的相同事件
  2. 所以我们就可以把子元素的事件委托给父元素来做
  3. 关键的核心是 使用 事件对象的target属性 判断 目标

7.4 target

  1. target 是事件对象上的属性,表示点击的目标

  2. 当触发点击事件的时候,点击在哪个元素上,target就是哪个元素

  3. 兼容:在其他浏览器中 event.target,在IE浏览器中 event.srcElement

    1. var target = e.target || e.srcElement;
  4. 返回结果是 点击的元素对象

  5. 通过 event.target.nodeName 获取 标签大写名称,实现判断元素

js
ul.addEventListener('click',(e)=>{
    if(e.target.nodeName==='LI'){
        console.log('li被点击了')
    }
})

7.5 事件委托的好处

  1. 事件委托可以精准的控制事件的处理函数,并不会出现唐突的冒泡行为
  2. 事件委托非常的节省性能,而且使用方便,不需要批量注册事件
  3. 事件委托在处理异步结构的时候,可以不需要考虑异步的先后顺序(暂时未学习异步)

8.阻止浏览器默认行为

事件对象.preventDefault();       针对 高版本浏览器生效

事件对象.returnValue = false;    针对 ie6/7/8低版本浏览器生效

阻止浏览器默认行为的 兼容

js
e.preventDefault?e.preventDefault():e.returnValue = false;

另一种方法就是在事件函数最后 return false;

方便好记

js
var a1 = document.querySelector('#a1');

a1.onclick = function(ev){
    var e = ev || window.event;
    e.preventDefault?e.preventDefault():e.returnValue = false;
    // return false;
}

document.oncontextmenu = function(ev){
    var e = ev || window.event;
    e.preventDefault?e.preventDefault():e.returnValue = false;
    // return false;
}

MIT Licensed