跳到主要内容

多标签页通信与数据同步

场景

用户在多个浏览器标签页打开同一个应用,需要在标签页之间同步数据(如登录状态、购物车、主题设置)。

方案对比

方案同源限制实时性复杂度兼容性
BroadcastChannel同源实时
localStorage 事件同源实时极好
SharedWorker同源实时一般
Service Worker同源实时
window.postMessage跨源实时极好

BroadcastChannel(推荐)

跨标签页通信
// 创建频道(同名频道自动连接)
const channel = new BroadcastChannel('app-sync');

// 发送消息
function broadcast(type: string, data: unknown) {
channel.postMessage({ type, data, timestamp: Date.now() });
}

// 接收消息
channel.onmessage = (e: MessageEvent) => {
const { type, data } = e.data;
switch (type) {
case 'LOGOUT':
// 其他标签页登出,当前页也退出
handleLogout();
break;
case 'THEME_CHANGE':
setTheme(data);
break;
case 'CART_UPDATE':
refreshCart(data);
break;
}
};

// 页面关闭时清理
window.addEventListener('beforeunload', () => channel.close());

localStorage 事件

storage 事件监听
// 当 localStorage 在其他标签页被修改时触发
window.addEventListener('storage', (e: StorageEvent) => {
if (e.key === 'user-session') {
if (e.newValue === null) {
// 其他标签页清除了 session → 登出
handleLogout();
}
}
});

// 注意:storage 事件不会在当前标签页触发,只在其他标签页触发

常见面试问题

Q1: 有哪些方式实现多标签页通信?

答案

5 种主要方式:BroadcastChannel(推荐,API 简洁)、localStorage storage 事件、SharedWorker、Service Worker postMessage、window.postMessage(适合跨域 iframe)。优先选 BroadcastChannel。

Q2: 用户在一个标签页登出,如何通知其他标签页?

答案

// 登出时广播
function logout() {
clearSession();
new BroadcastChannel('auth').postMessage({ type: 'LOGOUT' });
redirectToLogin();
}

// 其他标签页监听
new BroadcastChannel('auth').onmessage = (e) => {
if (e.data.type === 'LOGOUT') {
clearSession();
redirectToLogin();
}
};

相关链接