优雅!原生Js实现多标签页之间的数据共享如此简单
(创作者训练重磅回归,速戳上图了解详情)
大家好,我是石小石!一个热爱技术分享的开源社区贡献者,小册《油猴脚本实战指南[1]》作者。
最近在开发油猴脚本中遇到一个场景:用户在多个标签页中打开了同一个 Web 应用时,A 页面发送消息,其余所有页面能监听到消息(比如 A 页面退出,其余页面全部退出)。
?如果你对网页脚本开发感兴趣,参考:为什么推荐前端学习油猴脚本开发?[2]
?原本使用的是 GM_saveTab 相关 API 实现,但后来发现,原生 JS 通过BroadcastChannel和localStorage + storage事件也可以轻松解决多标签页之间数据共享的问题,简单记录一下。
使用 BroadcastChannel 进行标签页通信什么是 BroadcastChannel?BroadcastChannel是一种浏览器原生提供的 API,用于在同源的不同标签页之间进行通信。它就像一个广播站,你可以在任意标签页中 “发送消息”,其他监听了这个频道的页面就能接收到。
使用示例创建频道const channel = new BroadcastChannel('my-channel');
监听消息channel.onmessage = (e) = {
console.log('收到消息:', e.data);
};
发送消息channel.postMessage('你好,其他标签页!');
关闭频道channel.close();
示例:多标签页实时消息广播!DOCTYPE html
html
head
titleBroadcastChannel 示例/title
/head
body
BroadcastChannel 演示/h2
input id="msgInput" placeholder="输入要广播的消息" /
button onclick="sendMessage()"/button
ul id="log"/ul
script
const channel = new BroadcastChannel('demo_channel');
const log = document.getElementById('log');
channel.onmessage = (event) = {
const li = document.createElement('li');
li.textContent = `接收到消息: ${event.data}`;
log.appendChild(li);
function sendMessage() {
const input = document.getElementById('msgInput');
channel.postMessage(input.value);
input.value = '';
}
/script
/body
/html实际应用场景:
多标签页中保持消息通知一致实时登出同步(任一页面登出,其他页自动退出)多窗口之间状态广播(主题切换、设置同步等)使用 localStorage + storage 事件监听同步storage事件当我们想兼容老浏览器,或者不想引入 BroadcastChannel 时,localStorage也可以用来实现通信。虽然它本质上是一个持久化存储工具,但在另一个标签页更改localStorage时,当前页面会触发storage事件:
标签页 A:更改 localStorage
localStorage.setItem('laoliu',JSON.stringify({
type: '不想工作',
text: "只要胆子大,天天都是假"
}) );
标签页 B:接收消息
window.addEventListener('storage', (event) = {
if (event.key === 'laoliu') {
const msg = JSON.parse(event.newValue);
if (msg.type === '不想工作') {
alert('6666,你个老六');
}
}
});
我们可以利用这个特性来传递数据。
示例:使用 localStorage 进行数据同步!DOCTYPE html
html
head
titlelocalStorage + storage 事件/title
/head
body
localStorage 通信演示/h2
input id="msgInput" placeholder="输入要同步的消息" /
button onclick="syncMessage()"/button
ul id="log"/ul
script
const log = document.getElementById('log');
function syncMessage() {
const input = document.getElementById('msgInput');
localStorage.setItem('crossTabMessage', JSON.stringify({
text: input.value,
timestamp: Date.now()
}));
input.value = '';
}
window.addEventListener('storage', (event) = {
if (event.key === 'crossTabMessage') {
const data = JSON.parse(event.newValue);
const li = document.createElement('li');
li.textContent = `接收到消息: ${data.text}`;
log.appendChild(li);
}
});
/script
/body
/html注意事项:
storage事件只在「非当前修改页面」触发。所以发送方不会接收到消息,接收方会响应。建议发送消息时携带timestamp等唯一标识,避免缓存误判。特性对比特性BroadcastChannellocalStorage + storage是否跨标签页通信??是否跨域 / 跨源通信支持?(同源)?(同源)是否支持对象直接传输?(会自动序列化)?(需手动序列化)是否支持双向通信??(发送方收不到)浏览器兼容性新(Chrome 54+,Safari 15+)老(广泛兼容)如果我们只支持现代浏览器,BroadcastChannel是最佳选择,API 简洁、逻辑直观。需要兼容旧版浏览器时,localStorage方案依然是个不错的替代。
一个完整的封装 Demo为了让项目更优雅地使用这些功能,我还封装了一个简单的通用消息发布器:
class TabMessenger {
constructor(channelName = 'default') {
this.isBroadcastSupported = typeof BroadcastChannel !== 'undefined';
this.channelName = channelName;
if (this.isBroadcastSupported) {
this.channel = new BroadcastChannel(channelName);
} else {
window.addEventListener('storage', this._onStorage.bind(this));
}
}
onMessage(handler) {
if (this.isBroadcastSupported) {
this.channel.onmessage = (e) = handler(e.data);
} else {
this.storageHandler = handler;
}
}
postMessage(msg) {
if (this.isBroadcastSupported) {
this.channel.postMessage(msg);
} else {
localStorage.setItem('__tab_msg_' + this.channelName, JSON.stringify({
msg,
ts: Date.now()
}));
}
}
_onStorage(e) {
if (e.key.startsWith('__tab_msg_' + this.channelName)) {
const data = JSON.parse(e.newValue);
this.storageHandler?.(data.msg);
}
}
}
使用方式:
const messenger = new TabMessenger('myApp');
messenger.onMessage((data) = {
console.log('收到消息:', data);
});
messenger.postMessage('你好,其他页面!');
总结我们可以看到,不需要复杂的框架和依赖,仅使用原生 API,我们就能轻松实现标签页之间的数据同步。在多标签页同步的场景中:
「首选 BroadcastChannel」,简单清爽。「备用 localStorage + storage」,兼容好。AI编程资讯AI Coding专区指南:https://aicoding.juejin.cn/aicoding
点击"阅读原文"了解详情~
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线