ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

如何用 storage 事件实现 localStorage 跨标签页数据同步

如何用 storage 事件实现 localStorage 跨标签页数据同步 如何用 storage 事件实现 localStorage 跨标签页数据同步【免费下载链接】33-js-concepts 33 JavaScript concepts every developer should know.项目地址: https://gitcode.com/GitHub_Trending/33/33-js-concepts多标签页是浏览器应用的常态用户在标签页 A 里登出、切换主题或更新某项状态标签页 B 里的界面却还停留在旧数据。33-js-concepts 的 localStorage sessionStorage 概念文档 中专门讲了一个可直接落地的机制——storage事件当同一个 origin 下的另一个文档标签页/窗口修改了 localStorage 时浏览器会在其余标签页上触发该事件事件对象携带了变化的 key、旧值和新值你可以据此在每个标签页里自动同步数据。本文围绕这一事件给出监听写法、一个跨标签页同步登出的完整示例以及两种可核对的验证方式。适用前提与文档标注一致熟悉 DOM 和基本 JavaScript 对象理解 JSON 序列化 有助于读懂存储复杂数据的部分。Web Storage 自 2015 年 7 月起被所有主流浏览器支持属于 HTML5 规范的 Baseline 特性可以直接依赖。storage 事件的触发边界只有其他标签页收到动手之前先明确事件的两条边界它们直接决定代码怎么写storage事件只在其他标签页触发修改存储的那个标签页本身不会收到事件。文档将此标注为常见困惑点The storage event does NOT fire in the tab that made the change—only in OTHER tabs。事件只在同 origin协议 域名 端口的标签页之间传递。不同 origin 互相不可见也收不到事件。另一条边界决定了同步对象localStorage在同一 origin 的所有标签页/窗口之间共享而sessionStorage每个标签页独立隔离、互不相通。因此跨标签页数据同步这条路径只对localStorage成立sessionStorage适合放本标签页的临时状态如分步表单进度。事件对象上能读到什么StorageEvent携带五个属性文档中的定义如下表属性含义key发生变化的 key调用clear()时为nulloldValue变化前的值新增 key 时为nullnewValue新值删除 key 时为nullurl做出修改的那个文档的 URLstorageArea被修改的 Storage 对象localStorage 或 sessionStorage三个null语义是判断变化的关键newValue null说明 key 被删除oldValue null说明是新写入的 keykey null说明整个存储被clear()清空。在每个标签页添加监听主路径只有一步在每个需要同步的标签页的 JS 中注册监听器然后在回调里按event.key分发处理。文档给出的基础写法// Listen for storage changes from other tabs window.addEventListener(storage, (event) { console.log(Storage changed!) console.log(Key:, event.key) // The key that changed console.log(Old value:, event.oldValue) // Previous value console.log(New value:, event.newValue) // New value console.log(URL:, event.url) // URL of the document that changed it console.log(Storage area:, event.storageArea) // localStorage or sessionStorage })由于发出修改的标签页收不到事件如果该标签页自己也需要对修改做响应比如立即刷新自己的界面需要把这部分逻辑与storage事件分开实现——在写入代码处直接调用同一套响应逻辑文档明确指出了这一做法If you need to react to changes in the same tab, youll need to implement that logic separately from the storage event。文档示例跨标签页同步登出文档给了一个完整的认证场景示例任一标签页删除authToken后其他标签页跳到登录页任一标签页写入authToken后其他标签页刷新以应用登录态。注意这是文档示例其中用 localStorage 存 token 仅用于演示事件流程安全部分见文末限制。// In your authentication module function setupAuthSync() { window.addEventListener(storage, (event) { // User logged out in another tab if (event.key authToken event.newValue null) { console.log(User logged out in another tab) window.location.href /login } // User logged in another tab if (event.key authToken event.oldValue null) { console.log(User logged in from another tab) window.location.reload() } }) } // When user logs out function logout() { localStorage.removeItem(authToken) // This triggers event in OTHER tabs window.location.href /login }同步逻辑的核心就是localStorage.removeItem(authToken)这一行它在本标签页删除数据同时在其他标签页触发storage事件其他标签页的setupAuthSync()监听器据此执行跳转或刷新。同步对象数据写入时序列化事件里反序列化Web Storage 只能存字符串直接存对象会得到[object Object]。所以同步对象数据时写入方用JSON.stringify()序列化监听方在事件回调里对event.newValue做JSON.parse()newValue是字符串。文档推荐的带默认值与容错的封装可直接用于写入方const storage { set(key, value) { try { localStorage.setItem(key, JSON.stringify(value)) return true } catch (error) { console.error(Storage set failed:, error) return false } }, get(key, defaultValue null) { try { const item localStorage.getItem(key) return item ? JSON.parse(item) : defaultValue } catch (error) { console.error(Storage get failed:, error) return defaultValue } } }一个由文档事实组合出的最小示例写入方用storage.set(cart, cart)保存购物车其他标签页的storage回调里判断event.key cart后执行JSON.parse(event.newValue)拿到新购物车。两点要注意JSON 序列化会丢失Date变成字符串、undefined属性和函数读回Date需手动new Date(...)还原解析event.newValue前同样要有容错因为被删除的 key 会让newValue为null。两种可以核对的验证方式方式一双标签页手动验证文档给出的步骤文档提供了五步手动测试流程在两个浏览器标签页中打开你的站点必须同 origin。两个标签页都打开 DevTools 控制台。在标签页 1 添加监听window.addEventListener(storage, (e) console.log(Changed:, e.key))在标签页 2 修改存储localStorage.setItem(test, value)标签页 1 的控制台应打印出Changed: test文档示例输出。同时可以做反向核对在标签页 2做出修改的一方确认没有打印用于验证本标签页不触发这一边界。方式二单测中手动派发 StorageEvent仓库自带的 DOM 测试 localstorage-sessionstorage.dom.test.js 展示了在 jsdom 环境无法开两个真实标签页中模拟跨标签页变化的方法构造StorageEvent并window.dispatchEvent断言监听器收到正确的属性。最小写法如下取自该测试文件的模式const handler vi.fn() window.addEventListener(storage, handler) const event new StorageEvent(storage, { key: theme, oldValue: light, newValue: dark, url: http://example.com, storageArea: localStorage }) window.dispatchEvent(event) expect(handler).toHaveBeenCalledTimes(1) expect(handler.mock.calls[0][0].key).toBe(theme) window.removeEventListener(storage, handler)这个方式只验证你的监听逻辑对事件属性的处理是否正确不验证浏览器真实的双标签页触发行为两者应结合使用。限制与常见坑本标签页收不到事件这是最常见的问题来源。写入方不能依赖storage事件驱动自身 UI必须在写入处单独调用响应逻辑。配额各主流浏览器 localStorage 限额约 5 MB / origin文档同时给出 ~5–10 MB 的区间说法。超出限额时setItem()抛出QuotaExceededError写入方应 try-catch 并按错误名判断try { localStorage.setItem(key, value) } catch (e) { if (e.name QuotaExceededError) { // 存储已满清理旧数据或提示用户 } }隐私模式Safari 在隐私模式下对任何写入都抛QuotaExceededErrorChrome/Firefox/Edge 可用但关窗即清空。上线前用文档给出的特性检测函数storageAvailable(localStorage)先探测可用性不可用时降级到内存存储或提示用户。安全边界localStorage 暴露在 XSS 之下页面上任何脚本包括注入的恶意脚本都能读取它。文档明确不要把密码、支付信息、API key、认证 token 存进 Web Storage认证应使用 HTTP-only cookie上面登出示例中的authToken键仅用于演示事件流程不代表推荐把真实 token 放进 localStorage。sessionStorage 不可用于跨标签页它按标签页隔离一个标签页的修改不会出现在其他标签页也就构不成跨标签页同步通道。延伸如果数据超过 5 MB 或需要结构化索引文档建议换用 IndexedDB如果数据需要随 HTTP 请求发送到服务端应使用 cookies。完整的方法对照、更多模式与 FAQ 见 localStorage sessionStorage 原文档。【免费下载链接】33-js-concepts 33 JavaScript concepts every developer should know.项目地址: https://gitcode.com/GitHub_Trending/33/33-js-concepts创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表