Skip to content

事件处理

常见事件

H5 移动端

  • touchstart / touchmove / touchend / touchcancel: 基础触摸四件套。
  • Tap (轻触): 移动端点击,由于没有 hovertap 是最高频的交互。
  • Longpress (长按): 指尖接触超过一定时间(通常 350ms+)且位移极小时触发。
  • Swipe (滑动): 手指快速划过屏幕,通常通过计算 touchstarttouchend 的坐标差来实现(左划、右划、上滑、下滑)。
  • Pinch / Rotate (缩放/旋转): 涉及多指触控(event.touches.length > 1),常用于图片查看器或地图。

鼠标事件

  • click: 鼠标左键点击。
  • dblclick: 鼠标左键双击。
  • contextmenu: 鼠标右键点击(弹出系统菜单前触发,常用于自定义右键菜单)。
  • mousedown / mouseup: 鼠标按下与抬起。
  • mouseenter / mouseleave: 鼠标移入/移出元素边界(不冒泡,推荐使用)。
  • mouseover / mouseout: 鼠标移入/移出元素及其子元素(会冒泡,易产生冗余触发)。
  • mousemove: 鼠标在元素上移动。
  • wheel: 鼠标滚轮滚动(替代了废弃的 mousewheel)。

键盘事件

  • keydown: 按下按键时触发(按住不放会连续触发)。
  • keyup: 抬起按键时触发。
  • keypress: 按下产生字符的按键时触发(已废弃,建议统一使用 keydown)。
  • 补充 - 关键属性:
    • event.key: 返回按键的标识符(如 "Enter", "a", "ArrowLeft")。
    • event.code: 返回物理按键代码(如 "KeyA", "Digit1"),不受输入法或 Shift 键影响。

加载和卸载事件

  • DOMContentLoaded: HTML 文档被完全加载和解析完成,不等待样式表、图片等。(适合绑定 DOM 操作)
  • load (window.onload): 页面上所有资源(图片、CSS 等)全部加载完毕。
  • beforeunload / unload: 页面关闭或刷新前/后触发,常用于保存草稿或埋点统计。
  • readystatechange: document.readyState 变为 loadinginteractivecomplete 时触发。

拖放事件 (Drag & Drop)

开发技巧: dragover 必须调用 event.preventDefault(),否则 drop 事件不会触发。

  • 源元素 (Source):
    • dragstart: 开始拖动。
    • drag: 拖动过程中持续触发。
    • dragend: 拖动结束。
  • 目标元素 (Target):
    • dragenter: 进入目标区域。
    • dragover: 在目标区域内移动(每几百毫秒触发)。
    • dragleave: 离开目标区域。
    • drop: 在目标区域释放。

剪切板事件

  • copy / cut: 复制或剪切时触发。可以通过 event.clipboardData.setData() 修改剪切板内容。
  • paste: 粘贴时触发。可以通过 event.clipboardData.items 读取图片或文件(常用于实现聊天框粘贴上传图片)。

通信与存储

  • message: 跨文档通信。常用于 iframe 之间、Web WorkerpostMessage 接口。
  • storage: 注意: 只有在同一个域名下的其他窗口修改了 localStorage 时,当前窗口才会收到此事件(当前窗口自己修改不触发)。

视口与输入 (重要)

  • resize: 窗口大小改变。移动端键盘弹出可能触发此事件。
  • input: 输入框内容发生变化时立即触发(比 change 更及时)。
  • compositionstart / compositionend: 中文输入法选词开始与结束。(解决中文输入搜索防抖的利器)
  • visibilitychange: 页面可见性改变(如切换标签页、最小化),常用于暂停视频或心跳包。

💡 框架提示:在 React 中事件是合成事件(SyntheticEvent),Vue 中则利用指令(如 @touchstart.passive)简化了事件修饰符的使用。

定义事件

标签事件

html
<button onclick="handleClick()">Btn</button>

<script>
  const handleClick = function () {
    console.log('btn click')
  }
</script>

onXxx

html
<button id="btn">btn</button>

<script>
  const btn = document.querySelector('#btn')
  btn.onclick = function () {
    console.log('btn click')
  }
</script>

EventListener

addEventListener 有三种语法形式,如下:

  1. addEventListener(type, listener):默认情况下会在冒泡阶段触发监听器。
  2. addEventListener(type, listener, useCapture):是否在捕获阶段触发监听器,默认为 false
  3. addEventListener(type, listener, options):支持多个可选参数
    • capture:是否在捕获阶段触发监听器,默认为 false
    • once:是否只触发一次监听器,默认为 false
    • passive:是否在监听器中调用 preventDefault,默认为 false
    • signal:一个 AbortSignal 对象,用于取消监听器。
html
<button id="btn">btn</button>

<script>
  const btn = document.querySelector('#btn')
  const handleClick = function () {
    console.log('btn click')
  }
  btn.addEventListener('click', handleClick) // 添加事件监听器
  btn.removeEventListener('click', handleClick) // 移除事件监听器
</script>

event 事件对象

  • event.preventDefault():阻止默认行为。
  • event.stopPropagation():阻止事件传播。
  • event.target:触发事件的对象。
  • event.currentTarget:被监听的对象。

提示

event.currentTarget 永远都是指向被监听的对象,而 event.target 会随着使用者触发的对象去改变。

自定义事件

js
// e 代表触发的事件对象
window.addEventListener(
  'test',
  function (e) {
    if (e.myAttr === 'demo') {
      alert('key值为demo,添加成功!')
    }
  },
  false,
)

// 创建一个事件对象,名字为 test
let hbEventObj = new Event('test')

// 给事件对象添加一个属性,叫做 myAttr
hbEventObj.myAttr = 'demo'

// 触发事件
window.dispatchEvent(hbEventObj)

基于 MIT 许可发布