意思就是想要两个 tab页同时能获取到一个状态的更改。比如在 A 页面改的状态,在 B 页面也可以同时获取到
上文有提到两种同源的方式
store
这个 LocalStore、SessionStore的更新事件service worker
这个不了解,不过他说了应该是有道理的,下面我在补充一个API window.postMessage
window.postMessage - MDN 先贴下文档
window.postMessage() 方法可以安全地实现跨源通信。
/*
* A 窗口的域名是<http://example.com:8080>,以下是 A 窗口的 script 标签下的代码:
*/
var popup = window.open(...popup details...);
// 如果弹出框没有被阻止且加载完成
// 这行语句没有发送信息出去,即使假设当前页面没有改变 location(因为 targetOrigin 设置不对)
popup.postMessage("The user is 'bob' and the password is 'secret'",
"https://secure.example.net");
// 假设当前页面没有改变 location,这条语句会成功添加 message 到发送队列中去(targetOrigin 设置对了)
popup.postMessage("hello there!", "http://example.com");
function receiveMessage(event)
{
// 我们能相信信息的发送者吗?(也许这个发送者和我们最初打开的不是同一个页面).
if (event.origin !== "http://example.com")
return;
// event.source 是我们通过 window.open 打开的弹出页面 popup
// event.data 是 popup 发送给当前页面的消息 "hi there yourself! the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
/*
* 弹出页 popup 域名是 http://example.com,以下是 script 标签中的代码:
*/
//当 A 页面 postMessage 被调用后,这个 function 被 addEventListener 调用
function receiveMessage(event) {
// 我们能信任信息来源吗?
if (event.origin !== "http://example.com:8080") return;
// event.source 就当前弹出页的来源页面
// event.data 是 "hello there!"
// 假设你已经验证了所受到信息的 origin (任何时候你都应该这样做), 一个很方便的方式就是把 event.source
// 作为回信的对象,并且把 event.origin 作为 targetOrigin
event.source.postMessage(
"hi there yourself! the secret response " + "is: rheeeeet!",
event.origin,
);
}
window.addEventListener("message", receiveMessage, false);
好了贴完了
BroadcastChannel:BroadcastChannel 是一个新的浏览器 API,可以在不同的浏览器 tab 中进行实时通信。它类似于一个广播通道,可以将消息发送给所有订阅该频道的 tab。不过需要注意的是,BroadcastChannel API 目前不是所有浏览器都支持。
//// 发送端
// 创建 BroadcastChannel
const channel = new BroadcastChannel('my-channel');
// 监听 channel 的消息事件
channel.addEventListener('message', (event) => {
console.log('Received message:', event.data);
});
// 向 channel 发送消息
channel.postMessage('Hello from main thread!');
//// 接收端
// 创建 BroadcastChannel
const channel = new BroadcastChannel('my-channel');
// 监听 channel 的消息事件
channel.addEventListener('message', (event) => {
console.log('Received message:', event.data);
});
// 向 channel 发送消息
channel.postMessage('Hello from another tab!');
SharedWorker:SharedWorker 是一种可以在多个浏览器 tab 中共享的 JavaScript 运行环境。可以在 SharedWorker 中监听消息事件,从而实现浏览器 tab 之间的实时通信。
//// 发送端
// 创建 SharedWorker
const worker = new SharedWorker('worker.js');
// 监听 worker 的连接事件
worker.port.addEventListener('connect', (e) => {
console.log('Worker connected');
// 监听 worker 的消息事件
e.source.addEventListener('message', (event) => {
console.log('Received message:', event.data);
});
});
// 向 worker 发送消息
worker.port.postMessage('Hello from main thread!');
//// 接收端:
// 监听端口对象的消息事件
self.addEventListener('message', (event) => {
console.log('Received message:', event.data);
// 向所有连接的端口发送消息
self.clients.matchAll().then((clients) => {
clients.forEach((client) => {
client.postMessage(event.data);
});
});
});
以前遇到过这样的问题,用户可能打开了多个标签,其中有个标签是一个列表页面,如果在另外的页面中修改了数据,则希望这个打开的列表页面能够及时刷新,后面是通过BroadcastChannel这个实现的。
从设计角度看,
所有的功能都应该在同一个 Tab,
不讨论跨 Tab 的功能实现
毕竟有 iframe 为啥一定要实现多 Tab 的通信?
有啥实际的业务场景吗?
可以直接喷需求,
改成单页面的需求,
用 iframe 降级成稳定的单页面通信
想想论坛和聊天室就知道,
找后端开一个 WebScoket 岂不美哉?
没理由一定要前端康所有,
合理的诉求应该提出来
8 回答4.7k 阅读✓ 已解决
6 回答3.5k 阅读✓ 已解决
5 回答2.8k 阅读✓ 已解决
5 回答6.4k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
3 回答2.5k 阅读✓ 已解决
共享SessionStorage