如何实现 B 站多个窗口情况下同时退出&登陆?
- 今天正好接到一个需求,要求网站做到类似 B 站这样,当有多个窗口时,一旦某个窗口退出,其他窗口同步退出。
- 我观察到的现象是,一个窗口退出以后,其他窗口会同步发送一个网络请求。
问题:其他窗口是如何监听到另一个窗口的退出动作的呢?
题主补充(2023/6/6):最后采用设置 localstorage,并且 在 app.vue 里加载下面函数,完成需求
window.addEventListener("storage",(e)=>{
if(e.key=一些判断){
//TODO:触发页面重新刷新的逻辑
}
})
回复
1个回答
test
2024-07-02
1.WebSockethtml5提供的全双工通讯的协议,浏览器和服务器之间建立一条不受限的双向通信的通道,双向数据传输,需要服务端支持。
使用方法可参考:nodejs搭建websocket服务实现多页面通信
2.StorageEvent简单有效的方式,页面A通过storage存储消息,页面B监听storage即可捕获消息。
pageA.html:
<body>
<input type="text" id="msg">
<button id="send">发送</button>
<script>
send.onclick = function () {
let msg = document.getElementById("msg").value
localStorage.setItem('message', JSON.stringify({
message: msg,
from: 'pageA.html',
date: Date.now()
}))
}
</script>
</body>
pageB.html:
<body>
收到了消息:<span id="text"></span>
<script>
window.addEventListener('storage', function (e) {
// console.log(e.key, e.newValue, e.oldValue)
let msg = JSON.parse(e.newValue)
document.getElementById('text').innerText = msg.message
})
</script>
</body>
3.postMessage支持跨域通信,需要获取打开窗口的句柄(对象),建立联系,安全地实现跨源通信。
pageA.html:
<body>
<button id="openw">打开B页面</button>
<br>
<input type="text" id="msg">
<button id="send">发送</button>
<script>
let newWindow = null
openw.onclick = function () {
console.log(333)
newWindow = window.open('pageB.html')
}
send.onclick = function () {
let msg = document.getElementById("msg").value
if (newWindow)
newWindow.postMessage(msg)
}
</script>
</body>
pageB.html:
<body>
收到了消息:<span id="text"></span>
<script>
window.addEventListener('message', function (e) {
document.getElementById('text').innerHTML = e.data
})
</script>
</body>
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postM...
4.SharedWorker实现一个在浏览器后台运行的共享worker,页面通过该worker进行连接和信息的传递。同源
本地不支持,需要放到服务器。( webstorm可在浏览器中打开,vscode使用live server插件)测试。
worker.js:
let portList = [];
onconnect = function (e) {
let port = e.ports[0];
if (portList.indexOf(port) < 0)
portList.push(port);
port.onmessage = function (e) {
boardCast(e.data);
};
port.start();
};
function boardCast(data) {
portList.forEach(port => port.postMessage(data));
}
pageA.html:
<body>
<input type="text" id="msg">
<button id="send">发送</button>
<script>
if (!!window.SharedWorker) {
let myWorker = new SharedWorker("worker.js");
send.onclick = function () {
let msg = document.getElementById("msg").value
myWorker.port.postMessage(msg);
}
myWorker.port.start()
} else {
alert("当前浏览器不支持webworker!")
}
</script>
</body>
pageB.html:
<body>
收到了消息:<span id="text"></span>
<script>
if (!!window.SharedWorker) {
let myWorker = new SharedWorker("worker.js");
myWorker.port.onmessage = function (e) {
document.getElementById('text').innerText = e.data
}
myWorker.port.start()
} else {
alert("当前浏览器不支持webworker!")
}
</script>
</body>
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/SharedWorker
5.BroadcastChannel实现同 源 下浏览器不同窗口,Tab页,frame或者 iframe 下的 浏览器上下文 (通常是同一个网站下不同的页面)之间的简单通讯。
pageA.html:
<body>
<input type="text" id="msg">
<button id="send">发送</button>
<script>
let channel = new BroadcastChannel('BroadcastChannel-test')
send.onclick = function () {
let msg = document.getElementById("msg").value
channel.postMessage(msg)
}
</script>
</body>
pageB.html:
<body>
收到了消息:<span id="text"></span>
<script>
let channel = new BroadcastChannel("BroadcastChannel-test")
channel.addEventListener("message", function (e) {
document.getElementById('text').innerText = e.data
})
</script>
</body>
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Broadcast_Ch...
6.MessageChannel创建一个新的消息通道,并通过它的两个MessagePort 属性发送数据。常见场景iframe通信。
pageA.html:
<body>
<input type="text" id="msg">
<button id="send">发送</button>
<p>收到iframe消息:<span id="text"></span></p>
<iframe src="pageB.html" width='640' height='320'></iframe>
<script>
let iframe = document.querySelector('iframe');
send.onclick = function () {
let channel = new MessageChannel();
channel.port1.onmessage = onMessage
let msg = document.getElementById("msg").value
iframe.contentWindow.postMessage(msg, '*', [channel.port2]);
}
function onMessage(e) {
document.getElementById('text').innerHTML = e.data
}
</script>
</body>
pageB.html:
<body>
<input type="text" id="msg">
<button id="send">发送</button>
<p>收到main消息:<span id="text"></span></p>
<script>
window.addEventListener('message', onMessage);
let port = null
function onMessage(e) {
document.getElementById('text').innerHTML = e.data;
port = e.ports[0]
}
send.onclick = function () {
let msg = document.getElementById("msg").value
if (port)
port.postMessage(msg);
}
</script>
</body>
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/MessageChannel
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容