【JS Web API】聊一聊 storage 事件

2026-04-27 19:34:34
window.addEventListener('storage', onStorage)

初看名字,似乎是用来监听 localStorage 数据变化的,localStorage 变量值发生变化时便会触发 onStorage 回调。

但实际开发中,可能会遇到一个迷惑的情况:修改了 localStorage 变量值,预期的监听事件却没有触发,这是为什么呢?

正确触发条件是:浏览器同时打开多个标签页访问同一网站。当其中一个标签页内修改了 localStorage 变量值时,浏览器会向其它访问同一网站的所有标签页(不包括发起修改的那个标签页) 派发 storage 事件,触发它们注册的 onStorage 回调。

所以当网站只有一个标签页被打开,即使正确注册了监听器,事件也不会触发。

const onStorage = (e) => {
  console.log(e.isTrusted) // 值为true浏览器原生触发,值为false表示手动触发
  console.log(e.key)       // 被修改的 localStorage 变量名
  console.log(e.oldValue)  // 变量修改前的值
  console.log(e.newValue)  // 变量修改后的值
  console.log(e.url)       // 触发修改的页面 URL
}

在看别人写的代码时,我发现只打开了一个标签页,storage 事件会被触发。
这与上述一个标签页不会触发 storage 事件的机制似乎相悖。

一条有效的排查路径是:在 onStorage 回调中检查 e.isTrusted 属性。如果打印结果为 true,说明是浏览器原生触发行为,如果打印结果为 false,则说明事件是由开发者手动触发的。顺着这条线索全局搜索,往往会发现类似如下的手动触发代码:

const storageEvent = new StorageEvent('storage', { 
  key: 'token', 
  newValue: token, 
})
window.dispatchEvent(storageEvent)

关于 storage 事件应用场景也很丰富:

  1. 多标签页同步登入/登出状态:当用户在任意标签页登录或退出时,其它所有已打开的页面能实时获取状态更新;
  2. 购物车实时更新:当用户在一个商品页面增删购物车商品时,其它已打开的商品页面能立刻反映出最新的购物车内容;
  3. 实时主题切换:当用户在任一页面切换(例如亮色/暗色)主题时,所有其它同源页面的主题效果会立即同步。

返回首页

本文总阅读量  次
皖ICP备17026209号-3
总访问量: 
总访客量: