多标签通信
localStorage + storage 事件
事件在同一个域下的不同页面之间触发,即在 A 页面注册了 storge 的监听处理,只有在跟 A 同域名下的 B 页面操作 storage 对象,A 页面才会被触发 storage 事件
// 在其中一个标签页中
localStorage.setItem('message', 'hello world')
// 在其他标签页中监听 storage 事件
window.addEventListener('storage', function (event) {
if (event.key === 'message') {
console.log('Received message: ', event.newValue)
}
})
- 优点: 简单易用,兼容性好,跨域同源标签页可以共享数据。
- 缺点: 只能传递字符串类型的数据,数据存储在本地,会影响性能。
BroadcastChannel
对于同源下的所有浏览上下文,一个名称只对应一个通道。
// 创建一个 BroadcastChannel 实例
const channel = new BroadcastChannel('my-channel')
// 发送消息
channel.postMessage('Hello from another tab!')
监听消息
const channel = new BroadcastChannel('my-channel')
channel.addEventListener('message', (event) => {
received.textContent = event.data
})
- 优点: 高效,使用简单,支持复杂的数据类型(如对象),标签页、iframe、Web Worker 都可以参与。
- 缺点: 只能同源通信。
SharedWorker
// 在所有需要通信的标签页中创建连接
const worker = new SharedWorker('worker.js')
// 监听来自 SharedWorker 的消息
worker.port.onmessage = (event) => {
console.log('Received from worker: ', event.data)
}
// 发送消息到 SharedWorker
worker.port.postMessage('Hello Worker!')
- 兼容性不行
window.postMessage
// 在发送方标签页中
otherWindow.postMessage('Hello from another tab!', '*')
// 在接收方标签页中
window.addEventListener('message', (event) => {
console.log('Received: ', event.data)
})
- 优点: 允许跨域通信,使用简单,适用范围广。
- 缺点: 安全性需要特别注意,确保消息的接收方和发送方都校验消息来源。