在单页应用里,我们常需要在多个标签页或窗口之间共享某些状态,并且希望这些变量在页面关闭后再次打开仍然存在。单纯使用本地存储虽然能持久化,但难以做到多页面间的实时感知与复杂数据结构的保存。下面介绍一套组合方案来实现网页间持久化共享变量。

为什么localStorage不够用
localStorage确实可以把变量存在浏览器本地,同源下的不同页面都能读取。但它有两个明显短板:一是只能存字符串,复杂对象要手动序列化;二是当一个页面修改了值,其他页面只有在主动读取时才知道,虽然可以通过storage事件监听,但只限于同源且不能跨浏览器,也无法满足更即时的通信需求。
用BroadcastChannel做实时网页间通信
BroadcastChannel接口允许同源的多个文档之间相互发送消息。我们可以把变量的变更通过频道广播出去,其他页面收到后更新内存中的值。
// 创建广播频道
const channel = new BroadcastChannel('shared_var_channel');
// 发送共享变量更新
function setSharedVar(key, value) {
const data = { key, value, time: Date.now() };
channel.postMessage(data);
// 同时持久化到localStorage
localStorage.setItem('shared_' + key, JSON.stringify(value));
}
// 接收其他页面的更新
channel.onmessage = function(event) {
const { key, value } = event.data;
console.log('收到更新:', key, value);
// 这里可以更新页面上的显示
};
用IndexedDB持久化复杂变量
如果共享的变量是大型对象或需要结构化查询,localStorage就不太合适了。IndexedDB可以持久化保存任意结构化数据,并且容量大得多。
// 打开数据库
const request = indexedDB.open('shared_var_db', 1);
request.onupgradeneeded = function(event) {
const db = event.target.result;
if (!db.objectStoreNames.contains('vars')) {
db.createObjectStore('vars', { keyPath: 'name' });
}
};
function saveToIDB(name, value) {
const dbReq = indexedDB.open('shared_var_db', 1);
dbReq.onsuccess = function(e) {
const db = e.target.result;
const tx = db.transaction('vars', 'readwrite');
tx.objectStore('vars').put({ name, value });
};
}
function readFromIDB(name, callback) {
const dbReq = indexedDB.open('shared_var_db', 1);
dbReq.onsuccess = function(e) {
const db = e.target.result;
const tx = db.transaction('vars', 'readonly');
const getReq = tx.objectStore('vars').get(name);
getReq.onsuccess = function() {
callback(getReq.result ? getReq.result.value : null);
};
};
}
组合方案示例
把上面两者结合起来:页面加载时从IndexedDB读变量填充内存,用户修改时写IndexedDB并广播,其他页面收到广播后也写回内存,从而实现持久化且实时的网页间共享。
const channel = new BroadcastChannel('shared_var_channel');
channel.onmessage = function(ev) {
const { name, value } = ev.data;
// 更新内存变量
window.__shared[name] = value;
};
function updateShared(name, value) {
window.__shared = window.__shared || {};
window.__shared[name] = value;
saveToIDB(name, value);
channel.postMessage({ name, value });
}
// 初始化
readFromIDB('token', function(val) {
if (val) {
window.__shared = { token: val };
}
});
注意事项
- BroadcastChannel只在同源页面间有效,跨域无法通信。
- IndexedDB操作是异步的,注意回调或Promise封装。
- 敏感信息不要明文存本地,可考虑加密后再写。
通过上述方式,我们实现的不再是单纯的本地存储,而是多页面可感知、可持久化的共享变量机制。
localStorageIndexedDBBroadcastChannel修改时间:2026-07-27 15:21:31