全面解析浏览器事件系统
浏览器中的事件可以分为以下几类:
1. 鼠标事件
click
: 鼠标点击事件dblclick
: 鼠标双击事件mousedown
: 鼠标按钮按下事件mouseup
: 鼠标按钮释放事件mousemove
: 鼠标移动事件mouseover
: 鼠标移入元素事件mouseout
: 鼠标移出元素事件mouseenter
: 鼠标进入元素事件mouseleave
: 鼠标离开元素事件
2. 键盘事件
keydown
: 键盘按键按下事件keyup
: 键盘按键释放事件keypress
: 键盘按键按压事件(已废弃)
3. 表单事件
submit
: 表单提交事件reset
: 表单重置事件change
: 表单元素值改变事件input
: 输入框内容改变事件focus
: 元素获得焦点事件blur
: 元素失去焦点事件
4. 窗口事件
load
: 页面加载完成事件unload
: 页面卸载事件beforeunload
: 页面即将卸载事件resize
: 窗口大小改变事件scroll
: 页面滚动事件DOMContentLoaded
: DOM内容加载完成事件
5. 触摸事件
touchstart
: 触摸开始事件touchmove
: 触摸移动事件touchend
: 触摸结束事件touchcancel
: 触摸取消事件
6. 拖拽事件
drag
: 元素被拖拽时触发dragstart
: 拖拽开始事件dragend
: 拖拽结束事件dragover
: 拖拽元素在目标元素上移动事件dragenter
: 拖拽元素进入目标元素事件dragleave
: 拖拽元素离开目标元素事件drop
: 拖拽元素在目标元素上释放事件
7. 媒体事件
- [play](javascript:void(0)): 媒体开始播放事件
pause
: 媒体暂停事件ended
: 媒体播放结束事件volumechange
: 音量改变事件
8. 网络事件
online
: 浏览器获得网络连接事件offline
: 浏览器失去网络连接事件
9. 存储事件
storage
: Web Storage发生变化事件
10. 自定义事件
可以通过 CustomEvent
构造函数创建自定义事件,用于组件间通信。
浏览器事件系统补充
11. 页面生命周期事件
pageshow
: 页面显示事件(包括从缓存中恢复)pagehide
: 页面隐藏事件visibilitychange
: 页面可见性改变事件beforeprint
: 打印前事件afterprint
: 打印后事件
12. 焦点事件
focusin
: 元素即将获得焦点事件(支持冒泡)focusout
: 元素即将失去焦点事件(支持冒泡)
13. 剪贴板事件
copy
: 复制事件cut
: 剪切事件paste
: 粘贴事件
14. 动画事件
animationstart
: CSS动画开始事件animationend
: CSS动画结束事件animationiteration
: CSS动画重复事件
15. 过渡事件
transitionstart
: CSS过渡开始事件transitionend
: CSS过渡结束事件transitionrun
: CSS过渡运行事件transitioncancel
: CSS过渡取消事件
16. WebSocket事件
open
: WebSocket连接打开事件message
: 接收到消息事件error
: WebSocket错误事件close
: WebSocket连接关闭事件
17. Promise事件
unhandledrejection
: 未处理的Promise拒绝事件rejectionhandled
: 已处理的Promise拒绝事件
18. History事件
popstate
: 浏览历史改变事件hashchange
: URL哈希值改变事件
19. 设备相关事件
deviceorientation
: 设备方向改变事件devicemotion
: 设备运动事件orientationchange
: 屏幕方向改变事件
20. 其他重要事件
error
: JavaScript错误事件abort
: 资源加载被中止事件loadstart
: 资源开始加载事件progress
: 资源加载进度事件loadend
: 资源加载完成事件timeout
: 请求超时事件
事件传播机制
事件冒泡 (Event Bubbling)
- 传播方向: 从最内层元素向上传播到外层元素
- 触发顺序:
子元素
→父元素
→祖先元素
→document
- 默认行为: 大多数事件默认采用冒泡机制
// 示例:事件冒泡
document.getElementById('parent').addEventListener('click', function() {console.log('父元素被点击');
});document.getElementById('child').addEventListener('click', function() {console.log('子元素被点击');
});
// 点击子元素时,会先输出"子元素被点击",再输出"父元素被点击"
事件捕获 (Event Capturing)
- 传播方向: 从最外层元素向下传播到目标元素
- 触发顺序:
document
→祖先元素
→父元素
→目标元素
- 启用方式: 在
addEventListener
中将useCapture
参数设为true
// 示例:事件捕获
document.getElementById('parent').addEventListener('click', function() {console.log('父元素被点击');
}, true); // true 表示在捕获阶段触发document.getElementById('child').addEventListener('click', function() {console.log('子元素被点击');
}, true);
// 点击子元素时,会先输出"父元素被点击",再输出"子元素被点击"
事件代理 (Event Delegation)
定义
事件代理是一种利用事件冒泡机制来管理多个子元素事件的技术,通过在父元素上绑定事件监听器来处理所有子元素的事件。
核心原理
- 利用事件冒泡机制
- 在祖先元素上统一处理子元素事件
- 通过
event.target
确定实际触发事件的元素
优势
- 性能优化: 减少事件监听器数量
- 内存效率: 降低内存占用
- 动态元素支持: 自动处理动态添加的元素
- 维护简便: 集中管理事件处理逻辑
实现示例
javascript// 传统方式 - 为每个li元素绑定事件
const listItems = document.querySelectorAll('li');
listItems.forEach(item => {item.addEventListener('click', function() {console.log('点击了:', this.textContent);});
});// 事件代理方式 - 在父元素上统一处理
const list = document.querySelector('ul');
list.addEventListener('click', function(event) {// 通过 event.target 确定实际点击的元素if (event.target.tagName === 'LI') {console.log('点击了:', event.target.textContent);}
});
应用场景
- 动态列表项的事件处理
- 表格行或单元格事件处理
- 大量相似元素的事件管理
- 需要频繁添加/删除元素的场景
合成事件 (Synthetic Event)
-
概念: React等框架封装的跨浏览器事件系统
-
目的: 解决浏览器兼容性问题,提供统一的事件接口
-
特性
:
- 兼容所有浏览器
- 提供与原生事件相同的接口
- 支持事件池优化性能
// React中的合成事件示例
function Button() {const handleClick = (syntheticEvent) => {// syntheticEvent是React的合成事件对象console.log(syntheticEvent.target);// 阻止事件传播syntheticEvent.stopPropagation();};return <button onClick={handleClick}>点击我</button>;
}
事件流阶段
- 捕获阶段: 事件从
document
向下传播到目标元素 - 目标阶段: 事件到达目标元素
- 冒泡阶段: 事件从目标元素向上传播到
document
事件控制方法
stopPropagation()
: 阻止事件继续传播stopImmediatePropagation()
: 阻止事件传播并阻止同一元素上的其他事件监听器执行preventDefault()
: 阻止事件的默认行为