JavaScript 中的事件

发布于 2025-01-04 22:00:51 字数 8284 浏览 5 评论 0

一、绑定事件的方法

HTML 内联属性绑定

<div onclick="alert('fuck')"></div>

js 获取 DOM 元素添加事件属性

document.getElementById('box').onclick = function (){...}

使用 addEventListener()

第一种方法,HTML 内联属性绑定事件的方式不推荐,这违反了最佳实践。第二种方法的缺点是,只能同时给事件绑定一个 callback,所以推荐一直使用 addEventListener() 方法给元素绑定事件

如果要移除一个通过 addEventListener 添加的事件处理函数,那么给 removeEventListener 传递的两个参数必须与 addEventListener 的前两个参数完全相同。这意味着,给一个元素绑定匿名事件处理函数将无法被移除

二、事件流

事件流

页面中接收事件的顺序。分为三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段

事件冒泡

事件首先由嵌套层次最深的节点接收,然后沿 DOM 树依次逐级向父代节点传播。

事件捕获

不太具体的节点(或嵌套层次最浅的节点,通常是 document) 应该最先接收事件,然后沿 DOM 树依次向子代节点传递直到一个具体的子节点

三、绑定事件的方法

标准方法

el.addEventListener(eventName, handle, useCapture)

  • 描述:给 DOM 元素添加指定的事件处理函数
  • 参数:
    • {String} eventName 事件名称
    • {Function} handle 事件函数
    • {Boolean} useCapture 是否在事件捕获阶段触发事件,true 代表捕获阶段触发,false 代表在冒泡阶段触发

el.removeEventListener(eventName, handle)

  • 描述:移除通过 addEventListener 添加的事件处理函数
  • 参数:
    • {String} eventName 事件名称
    • {Function} handle 事件函数

如果要移除一个通过 addEventListener 添加的事件处理函数,那么给 removeEventListener 传递的两个参数必须与 addEventListener 的前两个参数完全相同。这意味着,给一个元素绑定匿名事件处理函数将无法被移除

IE8 及以下

addEventListener 和 removeEventListener 在 IE8 及以下不被支持

el.attachEvent(eventName, handle)

  • 描述:给 DOM 元素添加指定的事件处理函数
  • 参数:
    • {String} eventName 事件名称
    • {Function} handle 事件函数

el.detachEvent(eventName, handle)

  • 描述:移除通过 addEventListener 添加的事件处理函数
  • 参数:
    • {String} eventName 事件名称
    • {Function} handle 事件函数

对比

attachEvent/detachEvent 与 addEventListener/removeEventListener 的区别:

  • 由于 IE8 不支持事件捕获,所以通过 attachEvent/detachEvent 绑定的时间也只能在冒泡阶段触发
  • 通过 attachEvent/detachEvent 绑定的事件函数会在全局作用域中运行,即: this === window
  • 通过 attachEvent/detachEvent 绑定的事件函数以绑定时的先后顺序倒序被执行
  • attachEvent/detachEvent 的第一个参数要在事件名称前面加 'on'

四、事件对象

标准

属性

event.bubbles

  • 读写特性:只读
  • 描述:表示事件是否冒泡

event.cancelable

  • 读写特性:只读
  • 描述:表示事件是否可以取消事件默认行为

event.currentTarget

  • 读写特性:只读
  • 描述:currentTarget 的值始终等于 this,即指向事件所绑定到的元素

event.target

  • 读写特性:只读
  • 描述:真正触发事件的元素

event.defaultPrevented

  • 读写特性:只读
  • 描述:为 true 表示已经调用了 preventDefault()

event.detail

  • 读写特性:只读
  • 描述:与事件相关的细节信息

event.eventPhase

  • 读写特性:只读
  • 描述:调用该事件处理函数的阶段 1 表示捕获阶段 2 表示处于目标阶段 3 表示冒泡阶段

event.trusted

  • 读写特性:只读
  • 描述:为 true 表示事件是由浏览器生成的,false 表示事件是由人工使用 JavaScript 创建的

event.type

  • 读写特性:只读
  • 描述:事件类型

event.type

  • 读写特性:只读
  • 描述:事件类型
方法

event.preventDefault()

  • 描述:阻止事件的默认行为

只有 event.cancelable 属性为 true 的事件,才能够通过 preventDefault() 方法取消默认行为

event.stopImmediatePropagation()

  • 描述:与 event.stopPropagation() 一样,可以阻止事件冒泡,除此之外,还能阻止执行该语句之后的所有事件监听

IE 特有

IE 中获取事件对象的方法

IE 中获取事件对象的方法与绑定事件的方式有关

1、DOM0 级绑定事件的方式,即 el.onclick = function () {} ,其事件对象通过 window 获取:

el.onclick = function () {
  window.event
}

2、DOM2 级绑定事件对象的方式,即 el.attachEvent('click', function (event) {}) ,既可以通过 window 获取,也可以通过 event 参数获取:

el.attachEvent('click', function (event) {
  window.event
  // 或
  event
})
属性

event.srcElement

  • 读写特性:只读
  • 描述:与规范中的 event.target 属性相同。

event.returnValue

  • 读写
  • 描述:默认为 true ,如果将其设为 false 即可取消事件默认行为,相当于规范中的: event.preventDefault()

event.cancelBubble

  • 读写
  • 描述:默认为 false ,如果设为 true 即可取消事件冒泡,相当于规范中的: event.stopPropagation()

事件总结

在规范中,事件处理函数的 this 对象始终等于 event.currentTarget 属性,但在 IE 中就不一定。比如:使用 attachEvent 绑定的事件处理函数是在全局作用域中运行的,所以 this 对象指向 window,而不是 event.srcElement

对照表

| standard      | IE          |
| -------------   | -------------     |
| target      | srcElement      |
| preventDefault()  | returnValue = false   |
| stopPropagation() | cancelBubble = true   |

五、事件类型及讲解

UI 事件

load

window 上触发:当页面完全加载完,包括所有图像、js 文件、css 文件、<object>内嵌对象等等
<img>图片:当图片加载完成后触发
<script>/<link>:当 js 文件或 css 文件加载成功后,注意:<script>标签只能使用 HTML 内联属性添加事件的方式才能生效

resize

window 上触发:当窗口大小改变时

scroll

window 上触发:当滚动页面时
在可滚动元素上触发:当滚动可滚动的元素时

焦点事件

focus

当元素获得焦点时触发,不冒泡,但是可以在捕获阶段触发

blur

当元素失去焦点时触发,不冒泡,但是可以在捕获阶段触发

鼠标与滚轮事件

click

点击鼠标左键时触发

dblclick

双击鼠标左键

mousedown

按下鼠标任意按钮时触发

mouseup

释放鼠标按钮时触发

mouseenter/mouseleave 与 mouseover/mouseout 的区别

mouseenter 只会在鼠标在元素外部进入元素内部时触发,如果该元素有子节点,当移入其子节点内部时,会在捕获阶段在该节点触发,当鼠标再从子节点移出到该节点时,不会再触发。

父元素绑定事件,子元素溢出父元素,括号的数字代表 event.eventPhase 的值

1、先移入子元素:mouseover: 事件在捕获阶段触发一次(1) mouseenter: Firefox、chrome 先在 处于目标阶段触发一次 再在 捕获阶段触发一次(2-1)Safari 先在 捕获阶段触发 再在 处于目标阶段触发 (1-2)

1.2、从子元素直接移出到父元素:mouseover: 事件在处于目标阶段触发(2) mouseenter: 不触发事件

1.3、再从父元素直接移动到子元素:​mouseover: 在捕获阶段触发(1) mouseenter: 在捕获阶段触发(1)

2、先移入父元素:​mouseover: 在处于目标阶段触发(2) mouseenter: 在处于目标阶段触发(2)

2.1、再从父元素直接移动到子元素:​mouseover: 在捕获阶段触发(1) mouseenter: 在捕获阶段触发(1)

总结:

大前提:父元素绑定事件,子元素溢出父元素。如果只考虑在目标阶段触发的话,即 event.eventPhase 的值为 2 时,不妨把子元素覆盖的区域当做附加区,那么:

  • mouseover 触发时机: 鼠标从外部移入该元素,或从附加区移入该元素 mouseout 触发时机: 鼠标从该元素移到外部,或从该元素移到附加区
  • mouseenter 触发时机: 鼠标从外部移入附加区,或从外部移入该元素 mouseleave 触发时机: 鼠标从附加区移入外部,或从该元素移入外部
  • mouseover 和 mouseout 的作用区域 = 该元素区域 - (该元素 与 附加区交集) mouseenter 和 mouseleave 的作用区域 = 该元素区域 和 附加区并集
  • mouseover 先于 mouseenter mouseout 先于 mouseleave

鼠标事件 只有 mouseenter 和 mouseleave 不冒泡(但是可以在捕获阶段触发)

mouseover 和 mouseout 的相关元素:

  • 标准 event.relatedTarget
  • IE8 及以下 event.fromElement event.toElement

鼠标事件对象中的位置信息:

  • 客户区坐标位置:event.clientX/Y
  • 页面坐标位置:event.pageX/Y,注意:IE8 及以下版本不支持 pageX/Y,不过可以通过 clientX/Y + scrollLeft/Top 计算
  • 屏幕坐标位置(相对电脑屏幕的坐标位置):event.screenX/Y

修改键

event.shiftKey    // 按住 shift 键为 true
event.ctrlKey    // 按住 Ctrl 键为 true
event.altKey    // 按住 alt 键为 true
event.metaKey    // Mac 下按住 command 键为 true,windows 按住 Windows 键为 true

注意:IE8 及以下不支持 metaKey

键盘事件

keydown

按下键盘任意键时触发

keypress

按下键盘任意字符键时触发

keyup

松开键盘任意键时触发

可以通过 event.keyCode 获取键码

文本事件

textInput

输入框,文本在插入输入框之前触发, event.data 按下的字符

HTML5 事件

contextmenu

鼠标右键事件,常用于制定自定义菜单

beforeunload

在页面卸载之前触发,用来询问用户是否真的要离开该页面

该事件在 window 上触发,调用此方法的必须将 提示信息设置为 event.returnValue 的值,并 return 该值

  • 示例:
window.addEventListener('beforeunload', function (event) {
  event.returnValue = 'what?'
  return 'what?'
}, false)

DOMcontentLoaded

形成完整 DOM 树之后触发

注意:IE8 及以下不支持

pageshow

页面显示时触发, load 事件只会在第一次加载页面是触发,之后页面会被 bfcache (往返缓存)管理,通过前进后退按钮来显示页面时, load 事件并不会触发,但是 pageshow 事件会触发

pagehide

页面卸载时触发。

注意:pageshow/pagehide 必须添加到 window 对象上

hashchange

# 号后面的字符串发生变化时,在 window 对象上触发。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
25 人气
更多

推荐作者

IDC-hncloud

文章 0 评论 0

薆情海

文章 0 评论 0

mb_VjXiXQg5

文章 0 评论 0

爱,才寂寞

文章 0 评论 0

BE WATER

文章 0 评论 0

微信用户

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文