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 事件应用场景也很丰富:
↶ 返回首页 ↶