多页面localStorage覆盖问题
目录
1.背景
2.根本原因
3.解决方案
1.背景
接口调用平台为了提高体验性,切换环境和新打开页面时,能获取到之前在页面已经填写的一些信息,于是将这些信息存储到localStorage中,如下:
2.根本原因
-
localStorage 的特性:
- 同源策略:同一域名下的所有页面共享同一个 localStorage
- 同步操作:读写操作是同步且立即生效的
- 无作用域隔离:所有标签页/窗口共享相同存储空间
- 典型场景
// 页面A
localStorage.setItem('key', 'valueA');// 页面B(同时打开)
localStorage.setItem('key', 'valueB'); // 会覆盖页面A的值
3.解决方案
方案1:使用页面唯一标识符
// 页面加载时生成唯一ID
const pageId = `page_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;// 存储数据时添加前缀
function savePageData(data) {localStorage.setItem(`${pageId}_data`, JSON.stringify(data));
}// 读取数据
function loadPageData() {return JSON.parse(localStorage.getItem(`${pageId}_data`));
}
方案2:使用 sessionStorage(如果适用)
// 数据只在当前会话有效,不同标签页隔离
sessionStorage.setItem('key', 'value');
方案3:状态管理 + 存储合并,将当前页面的data数据重新存储到sessionStorage
// 1. 使用统一的数据结构
const store = {page1: { /* 数据 */ },page2: { /* 数据 */ }
};// 2. 保存时合并现有数据
function saveData(pageKey, data) {const allData = JSON.parse(localStorage.getItem('app_data')) || {};allData[pageKey] = data;localStorage.setItem('app_data', JSON.stringify(allData));
}
方案4:使用 BroadcastChannel API 同步
// 所有页面监听存储变化
const channel = new BroadcastChannel('storage_sync');channel.addEventListener('message', (event) => {if (event.data.type === 'storage_update') {// 更新本地数据}
});// 修改存储时通知其他页面
function safeSetItem(key, value) {localStorage.setItem(key, value);channel.postMessage({type: 'storage_update',key,value});
}
不同方案试用场景
方案 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
唯一ID | 需要严格隔离 | 完全隔离 | 需要自己管理清理 |
sessionStorage | 临时数据 | 自动隔离 | 页面关闭丢失 |
数据合并 | 需要共享部分数据 | 灵活 | 实现复杂 |
BroadcastChannel | 实时同步 | 即时更新 | 兼容性要求 |
我的场景:第一次打开页面时,希望加载历史数据,所以关闭页面不能丢失,所以不能用sessionStorage,采用数据合并的方式,将当前页面的数据重新存储到localStorage,这样每次都保存最后一次页面的localStorage数据。完美解决。