1. 通过localStorage实现
localStorage
是Web Storage API
的一部分,用于在客户端存储数据,JS为它提供了事件监听机制------storage
事件,通过监听storage
事件变化可以实现跨浏览器标签页通信。
下面是在vue中使用的示例代码:
代码
发送消息页面:
- 调用
setItem
方法,第一个参数是一个标识,第二个参数为传输的具体数据。
js
// 页面dom内容
<template>
<div class="send-message">
<div class="title">我是消息发送页面:</div>
<div class="content">
<el-button size="small" type="primary" @click="clickSend">点击按钮,发送消息</el-button>
<div>发送内容:{{ message }}</div>
</div>
</div>
</template>
// js部分
<script>
export default {
name: 'send-message',
data() {
return {
message: ''
}
},
methods: {
clickSend() {
// 随机数
const count = Math.floor(10000 * Math.random());
this.message = count;
// 此处标识的名字为sendMessage
window.localStorage.setItem('sendMessage', count);
}
},
}
</script>
接收消息页面:
- 通过监听事件
storage
得到的参数是一个对象,对象中的key
用来对应是否为目标来源对象。 - 最新的数据消息数据存储在
newValue
字段中,oldValue
字段为上一次消息通信时的数据。
js
<template>
<div class="get-message">
<div class="title">我是消息接收页面:</div>
<div class="content">
<div>接收内容:{{ message }}</div>
</div>
</div>
</template>
<script>
export default {
name: 'get-message',
data() {
return {
message: ''
}
},
mounted() {
window.addEventListener('storage', this.getMessage);
},
destroyed() {
window.remveEventListener('storage', this.getMessage);
},
methods: {
getMessage(e) {
console.log(e);
if (e.key === 'sendMessage') {
this.message = e.newValue;
}
}
},
}
</script>
下面是getMessage
方法接收参数在控制台中打印出来的具体信息:

页面效果:


2. 通过BroadcastChannel API实现
在同一应用中需要在不同标签页(或者iframe
)之间共享或同步信息时,BroadcastChannel API
简单且高效。
注意:
BroadcastChannel API
只能在同源(相同的协议、主机和端口)的上下文之间工作。不能使用BroadcastChannel
来实现跨域通信。当标签页关闭时,其对应的
BroadcastChannel
对象会被自动关闭,无需手动销毁
代码
1. 通信
我们沿用上面的dom代码,只修改js部分的代码。
消息发送页面:
- 在
mounted
钩子中创建一个BroadcastChannel
对象,通道名称为my-channel
; - 使用
postMessage
方法发送消息;
js
mounted() {
this.channel = new BroadcastChannel('my-channel');
},
methods: {
clickSend() {
const count = Math.floor(10000 * Math.random());
this.message = count; // 此处代码是为了在dom页面上展示用的,对通信的代码来说没有意义。
this.channel.postMessage(count);
}
}
消息接收页面:
- 在
mounted
钩子中创建一个指向同一频道名的BroadcastChannel
对象,即my-channel
; - 通过监听
onmessage
事件以接收消息;
js
mounted() {
this.channel = new BroadcastChannel('my-channel');
this.getMessage();
},
methods: {
getMessage(e) {
this.channel.onmessage = e => {
console.log(e);
this.message = e.data;
}
}
}
2. 回复消息
BroadcastChannel
还可以实现回复消息操作,代码如下:
发送消息页面:
- 在此页面也定义一个
getMessage
方法,用来监听onmessage
方法。
js
mounted() {
this.channel = new BroadcastChannel('my-channel');
this.getMessage();
},
methods: {
getMessage() {
this.channel.onmessage = e => {
this.message = e.data;
}
},
clickSend() {
const count = Math.floor(10000 * Math.random());
this.message = count; // 此处代码是为了在dom页面上展示用的,对通信没有什么影响。
this.channel.postMessage(count);
}
},
接收消息页面:
js
mounted() {
this.channel = new BroadcastChannel('my-channel');
this.getMessage();
},
methods: {
getMessage(e) {
this.channel.onmessage = e => {
console.log(e);
this.message = e.data;
// 通过postMessage可以选择性的回复消息
this.channel.postMessage(`我收到消息了${e.data}`)
}
}
}
页面效果:
发送消息页面:

接收消息页面:

3. 手动关闭 BroadcastChannel
当某些场景下,我们想手动关闭BroadcastChannel
通信,可以调用它的 close
方法。
js
clickCloseSend() {
this.channel.close();
}
3. 通过cookie实现
在js中,由于直接监听cookie的变化是不可能的,因为cookie是存储在浏览器中的,并且JavaScript没有提供直接监听cookie变化的事件或API,可以通过轮询或者其它方式来检测cookie的变化。
下面这个示例是使用最常见的方法定期轮询
cookie的值。通过设置一个定时器,每间隔两秒去查询一次。
注意:
- 这种方法应该谨慎使用,并仅在必要时使用。
- 此方法并不是实时的,并且可能会因为定时器的精度而引入一些延迟。
- 频繁地检查cookie可能会对性能产生一定的影响。
代码
发送消息页面:
js
clickSend() {
const count = Math.floor(10000 * Math.random());
// 此处代码是为了在dom页面上展示用的,对通信没有什么影响。
// this.message = count;
// 设置cookie
document.cookie = `sendData=${count}`;
},
接收消息页面:
- 再页面初始化时,定义一个定时器,每隔两秒钟轮询一次。
- 获取cookie,判断cookie中是否存在
sendData=
这个标识,若存在就将此段数据截取出来。
js
mounted() {
// 定时器
setInterval(this.getMessage, 2000);
},
methods: {
getMessage() {
const cookies = document.cookie;
const cookieArr = cookies.split(';');
let sendData = null;
for(let i = 0; i < cookieArr.length; i++) {
const cookie = cookieArr[i].trim();
if (cookie.startsWith('sendData=')) {
sendData = cookie.substring('sendData='.length, cookie.length);
break;
}
}
this.message = sendData;
}
}
这个示例的页面效果跟上面两种示例的效果一样,这里就不贴图了。
4. 通过window.postMessage实现。
window.postMessage
是Web API
中的一个方法,它允许来自不同源的文档安全地相互通信,通过调用 postMessage() 方法并指定目标窗口的origin
,可以将消息发送到其他标签页,并通过监听message
事件来接收消息。
代码
发送消息页面:
js
clickSend() {
const count = Math.floor(10000 * Math.random());
if (!this.targetWindow) {
this.targetWindow = window.open('http://example.cn/get-message', '_blank');
} else {
this.targetWindow.postMessage(count, 'http://example.cn');
// 或者通过在传输的数据中用一个key来标识,目标源可以设置为*, 下面的key字段用做标识,在数据接收时通过判断这个key的值来确定是否接受此数据。
// this.targetWindow.postMessage({key: 'send-data', data: count}, '*');
}
},
接收消息页面:
js
mounted() {
window.addEventListener('message', this.getMessage, false);
},
destroyed() {
window.remveEventListener('message', this.getMessage, false)
},
methods: {
getMessage(e) {
// 通过传输数据中的key来判断是否要接受数据。
// if (e.data.key === 'send-data') {
// this.message = e.data.data;
// }
this.message = e.data.data;
},
},
注意:
- 当使用
postMessage
时,请确保正确地验证消息的来源(event.origin
),以防止跨站脚本攻击(XSS)。- 发送和接收消息的双方必须遵守同源策略(Same-Origin Policy),除非消息被明确允许跨源发送。
- 如果你希望发送复杂的数据结构(如对象或数组),
postMessage
可以自动处理这些结构的序列化与反序列化。
5. 通过indexedDB实现
IndexedDB
是浏览器提供的一个客户端数据库,是一个事务型的数据库系统,能够存储大量结构化数据(包括文件/ blob),可以在不同的标签页之间存储和读取数据。其实它主要用于在用户浏览器中持久化存储数据(不同标签页中共享数据),而不是用于不同标签页或窗口之间的实时通信。
一个可行的方案是:一个标签页可以将数据写入IndexedDB
,其他标签页可以监听IndexedDB
的变化事件或定时从IndexedDB
中读取数据来实现数据的共享和状态的同步。
由于我没有试过这种方式(其实是自己懒),就不贴代码了,有兴趣的掘友可以自己研究一下。另外在使用indexedDB
的时候需要注意以下几点:
- 不同的浏览器可能对IndexedDB的支持程度和支持的版本有所不同,为了确保应用的稳定性和可用性,建议自己查查不同浏览器版本对IndexedDB的支持情况。
- IndexedDB的所有操作都是异步的,这意味着它们不会立即完成,而是稍后在事件循环中完成,所以需要正确管理回调函数、Promise或async/await,确保自己的代码按预期执行。
- IndexedDB操作可能会失败,例如由于数据库版本冲突、存储空间不足或其他原因。因此,始终要准备好捕获和处理错误。可以用
try...catch
来处理。
这篇文章就到这里了,有描述不正确的地方欢迎掘友们纠错~。