文章目录
事件介绍
- 和页面内容约定的事情
- 当该页面内容触发了约定的行为的时侯,则执行对应的事情
- 事件三要素
- 事件源:绑定事件的元素
- 事件类型:绑定的什么事件
- 事件处理程序(函数):当事件触发的时候要执行的事情(执行的函数)
- 比如:
divEle.onclick = clickFn()
divEle
就是事件源click
就是事件类型clickFn()
就是事件处理函数
- 事件注意事项
- 事件源触发对应行为的时候,才会执行绑定的事件处理函数
- 事件源触发对应行为的时候,执行事件处理函数,函数内的
this
指向事件源 - 所有元素都可以绑定键盘事件,但并不是所有元素都能触发键盘事件
- 一般键盘事件绑定给
window
、document
、html
、body
、表单输入框…
- 一般键盘事件绑定给
- 表单事件并不是只有在
form
标签内的表单元素才能触发- 单独的表单元素也可以触发表单事件
常见事件类型
1. 鼠标事件
click
- 鼠标左键单击事件
dblclick
- 鼠标左键双击事件
contextmenu
- 鼠标右键单击事件
mousedown
- 鼠标按键按下事件
mouseup
- 鼠标按键松开事件
mousemove
- 鼠标光标移动事件
mouseover
- 鼠标光标移入事件
mouseout
- 鼠标光标移出事件
mouseenter
- 鼠标光标移入事件
mouseleave
- 鼠标光标移出事件
wheel
- 鼠标滚轮滚动事件
mouseover
和mouseout
的鼠标事件,事件源的后代元素也会触发
mouseenter
和mouseleave
的鼠标事件,事件源的后代元素不会触发
2. 键盘事件
keydown
- 键盘按键按下事件
- 按键按下不松开会一直触发
- 键盘按键按下事件
keypress
- 键盘按键键入事件
- 按键按下不松开会一直触发
- 按键按下有对应的内容输入时才会触发
- 注意:enter按键按下也会触发
- 键盘按键键入事件
keyup
- 键盘按键松开事件
3. 表单事件
focus
- 获取焦点事件
blur
- 失去焦点事件
input
- 内容改变(输入)事件
- 只要内容变化就会触发
- 内容改变(输入)事件
change
- 内容改变事件
- 失去焦点时或获取焦点时内容有变化才会触发
- 内容改变事件
submit
- 表单提交事件
- 只能绑定给
form
表单标签 - 表单提交的时候触发
- 输入框中
enter
按键按下会触发 submit
提交按钮点击会触发button
按钮点击会触发
- 输入框中
- 只能绑定给
- 表单提交事件
reset
- 表单提交事件
- 只能绑定给
form
表单标签 - 只有点击
reset
重置按钮才会触发
- 只能绑定给
- 表单提交事件
4. 触摸事件
touchstart
- 触摸开始事件
touchmove
- 触摸移动事件
touchend
- 触摸结束事件
5. 其他事件
selectstart
- 选择开始事件
visibilitychange
- 页面可见性事件
document.visibilityState
的返回值表示页面可见性- 值为:
visible
表示页面可见 - 值为:
hidden
表示页面不可见
- 值为:
- 页面可见性事件
事件绑定
DOM0级事件
- 语法:
事件源.on事件类型 = 事件处理函数
- 特点:同一个事件源的同一事件类型只能绑定一个事件处理函数
- 最后绑定的会把之前绑定的给覆盖掉
// 获取元素
var divEle = document.querySelector('div')
// 准备的事件处理函数
function clickFn1 () {
console.log('click1')
}
function clickFn2 () {
console.log('click2')
}
// DOM 0级绑定事件
divEle.onclick = function () {
console.log('点击')
}
divEle.onclick = clickFn1
divEle.onclick = clickFn2
// 最终输出:'click2'
DOM2级事件(事件监听器/侦听器)
- 语法1:
事件源.addEventListener(事件类型, 事件处理函数)
- 特点:
- 同一个事件源的同一事件类型可以绑定多个事件处理函数,并且触发的时候按照绑定顺序依次执行事件处理函数
- 不能兼容低版本IE浏览器
- 特点:
- 语法2(了解):
事件源.attachEvent(on事件类型, 事件处理函数)
- 特点:
- 同一个事件源的同一事件类型可以绑定多个事件处理函数,并且触发的时候按照绑定顺序倒序执行事件处理函数
- 只能在低版本IE浏览器中使用
- 特点:
// DOM 2级绑定事件
divEle.addEventListener('click', function () {
console.log('点击')
})
divEle.addEventListener('click', clickFn1)
divEle.addEventListener('click', clickFn2)
// 最终输出:'点击' 'click1' 'click2'
事件解绑
- 事件解绑本质上就是移除绑定的事件处理函数
- DOM0级事件
- 语法:
事件源.on事件 = null
- 因为DOM0级事件是通过
=
赋值的形式绑定的,所以会将之前绑定的处理函数覆盖掉
- 因为DOM0级事件是通过
- 语法:
- DOM2级事件
- 注意:DOM2级事件解除事件处理函数的前提是在绑定的时候必须使用函数名变量绑定
// 此方式绑定的处理函数无法解除绑定 divEle.addEventListener('click', function () {})
- 语法1:
元素.removeEventListener(事件类型, 解绑的事件处理函数)
- 不能兼容低版本IE浏览器
- 语法2(了解):
元素.detachEvent(on事件类型, 解绑的事件处理函数)
- 只能用于低版本IE浏览器
事件对象
- 事件触发的时候会给事件处理函数传递一个描述本次事件相关信息的对象,这个对象就是事件对象
- 获取事件对象(只能在事件处理函数中获取)
- 通过事件处理函数的形参获取
- 默认事件触发执行事件处理函数的时候,会以参数的形式给函数传递事件对象
- 不能兼容低版本IE
- 在事件处理函数中通过
window.event
获取- 语法:
window.event
- 可以兼容低版本IE
- 语法:
- 兼容获取
- 语法:
e = e || window.event
- 语法:
- 通过事件处理函数的形参获取
鼠标事件相关信息
- 鼠标触发事件的按键信息
- 语法:
事件对象.button
- 以数字的形式返回,表示触发事件的鼠标按键
- 左键:
0
- 滚轮:
1
- 右键:
2
- 左键:
- 语法:
- 鼠标触发事件的坐标信息
- offset
- 语法:
事件对象.offsetX
- 语法:
事件对象.offsetY
- 获取鼠标相对于触发事件元素左上角的坐标
- 语法:
- client
- 语法:
事件对象.clientX
- 语法:
事件对象.clientY
- 获取鼠标相对于浏览器左上角的坐标
- 语法:
- page
- 语法:
事件对象.pageX
- 语法:
事件对象.pageY
- 获取鼠标相对于页面左上角的坐标
- 语法:
- screen
- 语法:
事件对象.screenX
- 语法:
事件对象.screenY
- 获取鼠标相对于显示器左上角的坐标
- 语法:
- offset
- 扩展
document.onwheel = function (e) {
e = e || window.event;
// e.deltaY表示滚轮滚动的距离,正数表示滚轮向下滚动,负数表示向上滚动
console.log(e.deltaY);
}
键盘事件相关信息
- 获取按键键码
- 语法:
事件对象.keyCode
或者事件对象.which
- 返回值:按键的键码
- 比如:按下
enter
按键返回键码为13
- 比如:按下
- 注意:
keypress
键盘事件中获取的字母按键键码区分大小写keydown
键盘事件中获取的字母按键键码不区分大小写
- 语法:
- 获取按键的内容
- 语法:
事件对象.key
- 比如:
- 按下字母
a
,返回'a'
- 按下
enter
按键,返回'Enter'
- 按下字母
- 比如:
- 语法:
事件对象.code
- 比如:
- 按下字母
a
,返回'keyA'
- 按下
enter
按键,返回'Enter'
- 按下左边的
ctrl
按键,返回'ControlLeft'
- 按下字母
- 比如:
- 语法:
- 组合按键
- 语法:
事件对象.ctrlKey
- 判断是否按下了
ctrl
按键
- 判断是否按下了
- 语法:
事件对象.shiftKet
- 判断是否按下了
shift
按键
- 判断是否按下了
- 语法:
事件对象.altKey
- 判断是否按下了
alt
按键
- 判断是否按下了
- 语法:
事件对象.metaKey
- 判断是否按下了
win
按键
- 判断是否按下了
- 组合键判断
- 返回值都是布尔值,
true
表示按下了对应的按键,false
则表示没有按下 - 比如:判断是否同时按下
ctrl + k
- 通过判断:
事件对象.ctrlKey && 事件对象.keyCode === 75
- 通过判断:
- 返回值都是布尔值,
- 语法:
浏览器默认行为
- 不需要我们绑定事件,只要行为触发则默认会执行的事情
- 比如:
- 点击
a
标签,会默认跳转href
地址 - 点击表单的提交按钮,表单会默认提交
- 页面鼠标右键单击,会默认弹出菜单
- 页面鼠标按下移动,会默认选中内容
- …
- 点击
- 比如:
- 阻止浏览器默认行为
- 行为触发的时候,默认行为不执行
- 需要再对应的事件中阻止
- 如何阻止浏览器默认行为:
- 在事件处理函数中,书写
return false
- 注意:
- 只能用于DOM0级事件
return false
一般书写在函数最后- 在
return false
之前的代码不能报错(抛出异常)
- 注意:
- 在事件处理函数中,通过事件对象阻止默认行为
- 语法1:
事件对象.preventDefault()
- 不能在低版本IE中使用
- 语法2(了解):
事件对象.returnValue = false
- 只能在低版本IE中使用
- 语法1:
- 在事件处理函数中,书写
- 阻止
form
表单默认提交行为,只能在submit
事件中阻止 - 阻止页面的默认选中内容,只能在
selectstart
事件中阻止 - 阻止浏览器鼠标右键点击出现默认菜单列表,只能在
contextmenu
事件中阻止 - …
- 行为触发的时候,默认行为不执行
事件目标
- 事件源
- 绑定事件的元素
- 在事件处理函数中通过事件对象可以获取到事件源
- 语法:
事件对象.currentTarget
- 语法:
- 事件触发
- 绑定事件的元素,其事件源可以触发绑定的事件
- 绑定事件的元素,其事件源的后代元素也可以触发绑定的事件
- 事件目标
- 事件触发的时候,准确触发事件的元素就是事件目标
- 如何获取事件目标:
- 在事件处理函数中通过事件获取
- 语法1:
事件对象.target
- 语法2(了解):
事件对象.srcElement
- 兼容低版本IE
- 语法1:
- 在事件处理函数中通过事件获取
- 注意:在事件处理函数中,
this
指向事件源
事件传播
- 元素的事件触发的时候,从事件目标开始沿着结构父级一直到
window
的元素都触发同类型事件- 事件传播的本质,就是事件行为的传播
- 事件传播的三个阶段
- 捕获阶段:从
window
向事件目标的顺序进行传播 - 事件目标:准确触发事件的元素
- 冒泡阶段:从事件目标向
window
的顺序进行传播 - 事件传播顺序:事件捕获阶段传播 --> 事件目标 --> 事件冒泡阶段传播
- 捕获阶段:从
- 浏览器的事件传播
- 主流浏览器
- 绑定的事件默认都是在冒泡阶段触发
- 但保留了在捕获阶段触发的能力
- 低版本IE浏览器
- 事件传播只有冒泡阶段,所有事件都只会在冒泡阶段触发
- 主流浏览器
- 绑定的事件,事件传播触发
- DOM0级事件
- 只会在冒泡阶段触发
- DOM2级事件
- 通过
addEventListener
绑定事件时,第三个参数可以指定事件在哪个阶段触发- 语法:
事件源.addEventListener(事件类型, 处理函数, 决定触发阶段)
- 第三个参数如果传递
false
或者不传递,则绑定的事件在冒泡阶段触发 - 第三个参数如果传递
true
,则绑定的事件在捕获阶段触发
- 第三个参数如果传递
- 语法:
- 扩展:第三个参数也可以是一个配合对象
- 语法:
{ capture:布尔值,表示是否在捕获阶段触发, once: 布尔值,表示是否只触发一次 }
- 语法:
- 通过
- DOM0级事件
阻止事件传播
- 不让事件按照既定的方式传播
- 在事件处理函数中,通过事件对象阻止
- 主流浏览器
- 在处理函数中:
事件对象.stopPropagation()
- 可以阻止事件传播,但不会阻止事件源的同类型后续事件处理函数的执行
- 在处理函数中:
- 低版本IE
- 在处理函数中:
事件对象.cancelBubble = true
- 在处理函数中:
- 主流浏览器
- 注意:
- 如果是阻止冒泡传播,则在内层阻止
- 如果是阻止捕获传播,则在外层阻止
- 扩展:
事件对象.stopImmediatePropagation()
- 可以阻止事件传播,并且会阻止事件源的同类型后续事件处理函数的执行
事件委托
- 将需要给元素绑定的事件,委托给元素结构父级中的某一个元素来绑定
- 原理:利用了事件冒泡传播机制
- 事件委托的实现
- 将原本要给元素绑定的事件(委托方),委托给结构父级元素绑定(代理方)
- 在事件处理函数中,通过事件目标找到原本需要绑定事件的元素
- 如何判断:可以通过节点名称,元素类名,元素内容等
- 在事件委托的处理函数中,不能通过
this
来表示目标元素,因为this
指向事件源
- 在事件处理函数中,通过事件目标找到原本需要绑定事件的元素
- 将原本要给元素绑定的事件(委托方),委托给结构父级元素绑定(代理方)
- 事件委托的优点
- 减少了DOM元素操作以及事件绑定
- 提高了页面DOM性能
- 对动态添加的元素更加友好
- 注意:就近原则,尽量不要委托给
body
、html
、document
、window
// 需求:给每一个ul>li绑定点击事件,弹窗输出li中的内容
// 方案1:给每一个li绑定事件,对动态添加的元素不友好(每一次新增或删除都需要重新遍历)
Array.from(ul.children).forEach(function (li) {
li.onclick = function () {
alert(this.innerText)
}
})
// 方案2:事件委托 --> 将所有的li点击事件委托给ul绑定
ul.onclick = function (e) {
// 可以通过节点名称来判断事件目标是否是委托方元素
if (e.target.nodeName == 'LI') {
// 此处才是委托方的事件逻辑代码
alert(e.target.innerText)
}
}