事件对象与事件类型

DOM中的事件对象

在DOM级事件处理程序中,无论使用的是哪一级的DOM事件处理程序,都会将一个event对象传入到事件处理程序当中。

对于所有事件,一般都会有下列成员

属性/方法 类型 说明
bubbles Boolean 表明事件是否可以冒泡
cancelable Boolean 是否可以取消事件的默认行为
currentTarget Element 事件处理程序当前正在到达并处理事件的那个元素
defaultPrevented Boolean 为true表示已经调用preventDefault()——DOM3级事件新增
detail Integer 与事件相关的细节部分
eventPhase Integer 调用事件处理程序的阶段 1:捕获 2:处于目标3:冒泡
preventDefault() Function 取消事件的默认行为
stopImmediatePropagation() Function 取消事件进一步冒泡,同时阻止事件处理程序被调用
stopPropagation() Function 取消事件的进一步冒泡
target Element 事件的目标
type String 事件的类型

在事件处理程序内部,对象this始终等于currentTarget的值。
注意区分target和currentTarget:如果事件处理程序在目标元素上,那么这两个值相等。但是如果事件处理程序在目标元素的父节点上,那么这两个值就是不相等的

1
2
3
4
let btn = document.getElementById('mybtn')
btn.onclick = function(event){
event.currentTarget === event.target //true
}
1
2
3
4
5
6
let b = document.body
b.onclick = function(event){
event.currentTarget === event.target //false
currentTarget //body
target //mybtn
}

阻止浏览器默认行为

W3C的方法是e.preventDefault(),IE则是使用e.returnValue = false

preventDefault是事件对象Event的一个方法,作用是取消一个目标元素的默认行为。如果元素没有默认行为,调用无效。什么元素有默认行为呢?如链接点我,提交按钮

return false:
JS的return false只会阻止默认行为,而jQuery则既阻止默认行为又防止对象冒泡
阻止浏览器默认行为兼容:

1
2
3
4
5
6
7
8
9
function stopDefault(e) {
var e = e || window.event;
if (e && e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
return false;
}

注意:只有cancelable属性设置为true时才能过使用preventDefault取消其默认行为

阻止事件冒泡

W3C的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true

stopPropagation是事件对象Event的一个方法,作用是阻止目标元素的冒泡事件,但是不会阻止默认行为

注意,由于IE不支持事件捕获,因此e.cancelBubble = true只能停止事件冒泡,但是e.stopPropagation()可以同时取消事件捕获和事件冒泡

阻止事件冒泡兼容:

1
2
3
4
5
6
7
8
function stopPropagation(e) {
var e = e || window.event;
if ( e && e.stopPropagation ){
e.stopPropagation();
}else{
e.cancelBubble = true;
}
}

事件类型

UI事件

UI事件指的是不一定与用户操作有关的事件

  • load:页面完全加载后在window上触发,当所有框架加载完毕后再框架集上触发,当图像加载完毕后在img元素上触发。
  • unload:当页面完全卸载后在window上触发,当所有框架都卸载后在框架集上触发。
  • resize:当窗口或框架大小变化在window或框架上面触发
  • scroll:当用户滚动带滚动条的元素时在该元素上面触发

焦点事件

  • blur:元素失去焦点时触发,不可以冒泡
  • focus:元素获得焦点时触发,不可以冒泡
  • focusin:元素获得焦点触发,可以冒泡
  • focusout:元素失去焦点时触发,可以冒泡

注意:虽然blur和focus不冒泡,但是可以在事件捕获阶段侦听到他们。

当焦点从一个元素移动到另一个元素时,会依次触发下面这些事件

  1. focusout
  2. focusin
  3. blur
  4. focus

鼠标事件

鼠标事件 描述
click 按下鼠标时触发
dblclick 双击鼠标时触发
mousedown 按下鼠标键时触发
mouseup 释放按下鼠标键触发
mousemove 鼠标在节点内部移动触发,持续移动,事件会持续触发(会有性能问题)
mouseenter 鼠标首次进入节点触发,进入子节点不会触发。(在节点内只会触发一次)
mouseover 鼠标进入节点触发,进入子节点会再一次触发
mouseout 鼠标离开节点触发,离开父节点也会触发
mouseleave 鼠标离开节点触发,离开父节点不会触发
contextmenu 鼠标右键(右键菜单)前触发,或按下右键菜单时触发

wheel| 滚动鼠标的滚轮时触发,继承WheelEvent接口|

mouseover 和 mouseenter 的共同点:鼠标进入一个节点触发

区别:

  • mouseover 会在子节点触发多次
  • mouseenter 只触发一次

mouseout 和 mouseleave 共同点: 鼠标离开一个节点时触发

区别:

在父元素内部离开一个子元素时,mouseout事件会触发。
在父元素内部离开一个子元素时,mouseout事件不会触发。

鼠标事件的位置

  • 客户区坐标位置
    鼠标事件是在浏览器的窗口特定位置上发生的,这个位置信息保存在事件对象的clientX和clientY
  • 页面坐标位置
    这个位置信心告诉你鼠标事件是在页面中什么位置发生的,保存在pageX和pageY中

PageX和clientX ,这个两个比较容易搞混,

  • PageX:鼠标在页面上的位置,从页面左上角开始,即是以页面为参考点,不随滑动条移动而变化,换句话说,从滚动页面的左上角开始计算
  • clientX:鼠标在页面上可视区域的位置,从浏览器可视区域左上角开始,即是以浏览器滑动条此刻的滑动到的位置为参考点,随滑动条移动 而变化.

移动端设备

由于没有鼠标,所以移动端的鼠标事件有一定区别与变化

  • 不支持dbclick事件,双击浏览器窗口会放大画面,而且没有办法改变这个事件
  • 点击可单机元素会触发mouseover事件,如果这个事件不会导致屏幕发生变化,那么会依次发生mousedown、mouseup、click事件。否则不再有其他事件发生
  • mousemove事件也会触发mouseover和mouseout事件

触摸事件

  • touchstart:手指触摸屏幕时触发
  • touchmove:手指在屏幕上滑动时连续触发。在这个事件发生期间调用preventDefault()可以阻止滚动
  • touchend:手指从屏幕移开时触发
  • touchcancel:系统停止跟踪触摸事件时触发

html5事件

contextmenu事件

调出上下文菜单触发的事件,简单来说就是在windows下点击鼠标右键,在mac下Ctrl+单击。有时候我们需要给网页设置自定义的上下文菜单,于是contextmenu事件出现了。

由于这个事件是冒泡的,所以可以为document指定一个事件处理程序,用来代理页面中发生的所有此类事件。搭配preventDefault使用可以取消默认的上下文菜单,从而自定义上下文菜单。然后通过clientX和clientY来设置自定义菜单显示的位置,设置visible来控制自定义菜单的显示与隐藏。

beforeunload事件

在页面卸载前触发事件,让开发者在页面被卸载前阻止操作,但是需要注意的是,这个事件旨在页面卸载前提醒用户,询问用户是否离开页面,不能完全阻止页面被卸载

DOMcontentloaded事件

  • 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。
  • load 仅用于检测一个完全加载的页面,页面的html、css、js、图片等资源都已经加载完之后才会触发 load 事件。

hashchange事件

HTML5新增的hashchange事件,以便在URL参数列表发生变化时通知开发者

前端路由的hash实现

www.test.com/#/ 就是 Hash URL,当 # 后面的哈希值发生变化时,可以通过 hashchange 事件来监听到 URL的变化,从而进行跳转页面,并且无论哈希值如何变化,服务端接收到的 URL 请求永远是 www.test.com

1
2
3
window.addEventListener('hashchange', () => {
// ... 具体逻辑
})

Hash 模式相对来说更简单,并且兼容性也更好

前端路由的history实现
History 模式是 HTML5 新推出的功能,主要使用 history.pushState 和 history.replaceState 改变 URL

通过 History 模式改变 URL 同样不会引起页面的刷新,只会更新浏览器的历史记录。

1
2
3
4
// 新增历史记录
history.pushState(stateObject, title, URL)
// 替换当前历史记录
history.replaceState(stateObject, title, URL)

当用户做出浏览器动作时,比如点击后退按钮时会触发 popState 事件

1
2
3
4
window.addEventListener('popstate', e => {
// e.state 就是 pushState(stateObject) 中的 stateObject
console.log(e.state)
})

两种模式对比

  • Hash模式只可以更改 # 后面的内容,History 模式可以通过 API 设置任意的同源 URL
  • History 模式可以通过 API 添加任意类型的数据到历史记录中,Hash 模式只能更改哈希值,也就是字符串
  • Hash 模式无需后端配置,并且兼容性好。History 模式在用户手动输入地址或者刷新页面的时候会发起 URL 请求,后端需要配置 index.html 页面用于匹配不到静态资源(就像nginx配置react路由)

关于冒泡

不支持冒泡的事件

UI事件

  • load
  • unload
  • scroll
  • resize

焦点事件

  • blur
  • focus

鼠标事件

  • mouseleave
  • mouseenter
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2015-2021 AURORA_ZXH
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信