写在前面
今天说一下跨标签通信的一种实现方式,首先跨标签指的是同一个浏览器中不同标签之间进行数据通信,也就是说比如在第一个标签写了一个数据,在另一个标签里面进行数据的使用,而且是实时的
先说现象
当我点击发送消息给标签二的时候,标签二就立刻收到了发送的消息内容,并渲染到页面上,这是现象
为什么不用 vuex 或者是 pinia
使用这些的前提是单页面单标签的使用,是不涉及到多标签的,所以他们的数据在不同标签之间也是不共享的
为什么不用 localStorage
因为localStorage是共享,但是不是实时的,无法做到页面不刷新就更新数据的目的
实现方案之一:BroadcastChannel
MDN-BroadcastChannel
他的实现过程是很简单的,通过一个实例发送一条广播出去,这个时候浏览器可以通过监听消息的方式进行获取对应的实例的消息内容,如果不想监听了,就直接调用他自己的方法进行关闭即可
代码实现
// TODO: 创建一个BroadcastChannel的实例
const BC = new BroadcastChannel('tagCommunication-channel')
/**
* TODO: 发送消息给所有的监听标签页
* @param {any} 广播消息的内容
*/
const sendMessages = (obj = {}) => {
console.log("🚀 广播一条消息:", obj)
BC.postMessage(obj)
}
/**
* TOOD: 接收消息
* @param {Function} 接收消息的回调方法
*/
const receiveMessages = (cb) => {
if (cb) {
BC.addEventListener('message', (e) => {
console.log("🚀 接收到的广播消息:", e)
cb(e.data)
})
} else {
console.error('🚀 回调函数是必传项')
}
}
// TODO: 关闭接收广播 以便于JS的垃圾回收
const closeMessage = () => {
BC.close()
}
函数调用- 标签一
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>标签一</title>
<script src="./crossTagCommunication.js"></script>
</head>
<body>
<button onclick="sendMsg()">发送消息给标签二</button>
<script>
// TODO: 发送一条广播
function sendMsg() {
const data = {
name: 'tom',
age: 16
}
sendMessages(data)
}
</script>
</body>
</html>
函数调用-标签二
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>标签二</title>
<script src="./crossTagCommunication.js"></script>
</head>
<body>
<span id="msg">收到的消息</span>
<script>
// TODO: 设置获取到的消息进行处理
const setMessage = (data) => {
let pageDom = document.getElementById('msg')
pageDom.innerText = data.name
// TODO: 接收结束 关闭广播
closeMessage()
}
// TODO: 自执行函数进行接收获取到的广播消息
(() => {
receiveMessages(setMessage)
})()
</script>
</body>
</html>
打完收工
这总跨标签的实现方案是有很多的,这只是其中一种,感兴趣的可以自己搜一下一共有多少种方案,我之前写过的 workerjs 也是可以实现的,感兴趣的可以去看看,拜拜!