JavaScript 中的 window.addEventListener 详解

前言

今天在写代码时,遇到一个场景,需要监听 localStorage 的变化,脑海中快速浮现出了 2 个方案:

  1. 通过 setInterval 定时轮询 localStorage 的值是否变化。
  2. 重新localStorage 的 setItem 方法,手动派发一个自定义事件。

然后本着“能用原生就别用轮询”的原则,我去问了 GPT 是否有更优雅的解决方案~

window.addEventListener 是开发中使用非常高频的一个 API,那么我为什么没有第一时间想到它呢,是不是对它的用法还不够熟悉?

于是有了这篇文章,详细讲解一下 window.addEventListener 的用法,也算温故而知新吧。

正文

window.addEventListener 是开发中经常会用到的一个核心 API,通过它可以监听多种类型的事件,那么它都可以监听哪些类型的事件呢?

常见的事件类型可按功能分类如下:

1. 窗口尺寸与滚动相关事件

  • resize:窗口大小发生变化时触发。
  • scroll:窗口滚动时触发。

示例:

  1. window.addEventListener('resize', function() {
  2. console.log('窗口尺寸发生变化');
  3. });
  4. window.addEventListener('scroll', function() {
  5. console.log('窗口滚动了');
  6. });
JavaScript复制

2. 存储相关事件

  • storage:同源的其他页面通过 localStorage/sessionStorage 发生更改时触发(当前页面不会触发)。

示例:

  1. window.addEventListener('storage', function(event) {
  2. console.log('存储发生变化', event);
  3. });
JavaScript复制

场景扩展:当前页面如何监听 localStorage 的变化?

在实际开发中,常见场景是:同一个项目下有两个同级兄弟组件都依赖 localStorage 的某个值,如果在一个组件中修改了 localStorage,如何让另一个组件感知到变化?

关键点:如果兄弟组件在同一个页面内,直接监听 storage 事件是无效的,需要借助自定义事件或状态管理。

同一页面内兄弟组件通信

可以通过自定义事件或全局状态管理(如 Vuex/pinia)实现:

  1. // 组件A中修改 localStorage 后,派发自定义事件(不带参数)
  2. localStorage.setItem('yourKey', 'newValue');
  3. window.dispatchEvent(new Event('localStorageChange'));
  4. // 组件B中监听自定义事件
  5. window.addEventListener('localStorageChange', () => {
  6. // 读取最新 localStorage
  7. const value = localStorage.getItem('yourKey');
  8. // 处理逻辑
  9. });
JavaScript复制

自定义事件需要传递参数?

可以通过 CustomEvent 构造函数的 detail 字段传递参数:

  1. // 组件A中派发自定义事件并传递参数
  2. const data = { key: 'yourKey', value: 'newValue' };
  3. window.dispatchEvent(new CustomEvent('localStorageChange', { detail: data }));
  4. // 组件B中监听并获取参数
  5. window.addEventListener('localStorageChange', (event) => {
  6. // event.detail 即为传递的参数对象
  7. console.log('收到参数:', event.detail);
  8. // 也可以结合 localStorage 读取最新值
  9. });
JavaScript复制

3. 页面生命周期与导航事件

  • load:页面加载完成时触发。
  • beforeunload:页面即将卸载时触发。
  • unload:页面卸载时触发。
  • hashchange:URL hash 变化时触发。
  • popstate:浏览器历史记录发生变化时触发。

示例:

  1. window.addEventListener('load', function() {
  2. console.log('页面加载完成');
  3. });
  4. window.addEventListener('beforeunload', function(event) {
  5. event.preventDefault();
  6. event.returnValue = '';
  7. });
  8. window.addEventListener('hashchange', function() {
  9. console.log('hash 变化了');
  10. });
JavaScript复制

4. 网络与设备相关事件

  • online/offline:网络状态变化时触发。
  • orientationchange:设备方向变化时触发(移动端)。

示例:

  1. window.addEventListener('online', function() {
  2. console.log('网络已连接');
  3. });
  4. window.addEventListener('offline', function() {
  5. console.log('网络已断开');
  6. });
JavaScript复制

5. 剪贴板与输入相关事件

  • copy/cut/paste:剪贴板操作时触发。

示例:

  1. window.addEventListener('copy', function() {
  2. console.log('内容被复制');
  3. });
JavaScript复制

6. 其他常用事件

  • message:接收到 postMessage 消息时触发。
  • error:全局错误捕获。
  • keydown/keyup/keypress:键盘事件。

示例:

  1. window.addEventListener('message', function(event) {
  2. console.log('收到消息', event.data);
  3. });
  4. window.addEventListener('error', function(event) {
  5. console.error('捕获到错误', event.message);
  6. });
JavaScript复制

总结

window.addEventListener 支持监听多种类型的事件,常见的有:

  • 窗口尺寸与滚动(resize, scroll)
  • 存储(storage)
  • 生命周期与导航(load, beforeunload, hashchange, popstate)
  • 网络与设备(online, offline, orientationchange)
  • 剪贴板(copy, cut, paste)
  • 其他(message, error, 键盘事件等)
编程笔记 & 随笔杂谈