跨页面通信主要依赖浏览器提供的多种API实现,通过不同技术方案解决数据传递、状态同步等需求。以下是常见方法及适用场景:
Broadcast Channel API
创建同名频道实现发布-订阅模式,同源页面间可实时收发消息且不会回传自身。兼容主流浏览器(除IE),适合标签页间轻量级通信。
LocalStorage/SessionStorage
通过storage事件监听存储变化,实现数据共享。适用于同源页面间简单数据同步,如用户登录状态传递。
window.postMessage
允许跨窗口(包括不同域)安全通信,需指定目标窗口的origin。常用于iframe与父页面或新开窗口间的双向交互。
SharedWorker
共享Web Worker实现多页面间持久化通信,通过postMessage传递结构化数据。适合需要复杂逻辑处理或数据共享的场景,如多标签协同编辑。
WebSocket
建立长连接实现全双工通信,依赖服务端转发消息。适用于高实时性需求,如聊天室、股票行情推送等跨页面广播场景。
Service Worker
作为代理层拦截请求并管理消息,支持离线通信。结合:ml-search[Push API]可实现后台消息推送,常用于PWA应用。
IndexedDB
通过数据库读写共享结构化数据,适合需要持久化存储且频繁更新的场景,如离线应用多页面状态同步。
选择建议:轻量级数据同步可优先使用Broadcast Channel或LocalStorage;跨域场景适用postMessage;高实时性需求推荐WebSocket;复杂状态管理可结合SharedWorker或IndexedDB。
BroadcastChannel实现浏览器内多个标签页(.html)之间的通信
BroadcastChannel是一个Web API,用于在浏览器的不同窗口、标签页或者甚至不同的浏览器实例之间建立通信。它允许在同一个origin(来源)下的不同上下文之间发送数据,例如在同一个域名下的不同页面之间进行通信。
-- 创建频道
const channel = new BroadcastChannel('id_a');
-- 发送消息
channel.postMessage('Hello from sender!');
-- 接收消息
channel.onmessage = function(event) {
console.log('Received message: ', event.data);
};
-- 关闭频道
channel.close();
接收页面
<script>
const channel = new BroadcastChannel('id_a');
channel.onmessage = function (event) {
let body = document.querySelector('body');
body.textContent = event.data;
};
</script>
发送页面
<div>
<input type="text" placeholder="请输入内容">
<button onclick="handleSend()">发送消息</button>
</div>
<script>
const channel = new BroadcastChannel('id_a');
function handleSend() {
let input = document.querySelector('input');
if (input.value) channel.postMessage(input.value);
}
</script>
SharedWorker实现浏览器内多个标签页(.html页面)之间的通信
1、步骤
第一步,新建一个文件夹sharedWorker。
第二步,在sharedWorker文件夹里面创建三个同级文件,分别是:worker.js/send.html/reception.html。
2、worder.js文件代码
// 在所有sharedWorker共享的worker.js中,
// 保存一个data变量,
// 用于存储多个worker共享的数据
let data = "连接成功";
// 必须提供一个名为onconnect的事件处理函数
// 每当一个页面中new SharedWorker("worker.js")时,
// 就会为新创建的worker绑定onconnect事件处理函数
onconnect = function(e) {
// 获得当前连接上来的客户端对象
let client = e.ports[0];
client.postMessage(data);
// 当当前对象收到消息时
client.onmessage = function(e) {
// 如果消息内容为空,
// 说明该客户端想获取共享的数据data
if (e.data === "") {
// 就给当前客户端发送data数据
client.postMessage(data);
} else {
// 否则如果消息内容不为空,
// 说明该客户端想要提供
// 新的消息保存在共享的data中,
// 供别人获取
data = e.data;
}
};
};
3、send.html文件代码
// 注意:要写js文件路径
// 因为是平级所以不需要加路径
let worker = new SharedWorker("worker.js");
// start是ShatedWorker的一个方法
// start方法开启SharedWorder
worker.port.start();
// 发送数据
send.onclick = function () {
if (msg.value.trim() !== "") {
worker.port.postMessage(msg.value.trim());
};
};
4、reception.html文件代码
<div>
<span>收到消息:</span>
<span id="recMsg"></span>
</div>
let worker = new SharedWorker("worker.js");
// 3. 当worker.js中给当前客户端返回了data,
// 会触发当前客户端的message事件。
// data的值自动保存进事件对象e的data属性中
worker.port.addEventListener("message", function (e) {
recMsg.innerHTML = e.data;
});
worker.port.start();
// 1. 接收端反复向共享的worker.js对象中发送空消息,
// 意为想获取data的值
setInterval(function () {
worker.port.postMessage("");
// 2. 只要发送消息,
// 就触发worker.js中的onmessage,
// onmessage判断是空消息内容,
// 说明客户端想获得data。
// 于是就用postMessage()方法,
// 将data返回给当前客户端
}, 500);
localStorge实现浏览器内多个标签页(.html)之间的通信
1、reception.js接收页面
<div>
<span>收到消息:</span>
<span id="recMsg1"></span>
</div>
<div>
<span>收到消息:</span>
<span id="recMsg2"></span>
</div>
function load() {
// getItem: 获取localStorage里面的值
recMsg1.innerHTML = localStorage.getItem("msg1");
recMsg2.innerHTML = localStorage.getItem("msg2");
};
load();
// 只要任何页面修改了localStorage中的值,
// 都会自动触发其他页面中的storage事件。
// window监听事件
// window.addEventListener("storage", load);
// window.addEventListener("storage", load, true);
window.addEventListener("storage", load(), true);
2、send.js发送页面
<input id="msg1" type="text" />
<br />
<input id="msg2" type="text" />
<br />
<button id="send">发送</button>
send.onclick = function() {
// trim: 去除字符串的头尾空格
if (msg1.value.trim() !== "" && msg2.value.trim() !== "") {
// setItem: 往localStorage对象中添加数据
// trim: 去除字符串的头尾空格
localStorage.setItem("msg1", msg1.value.trim());
localStorage.setItem("msg2", msg2.value.trim());
};
};
3、注意
存在兼容性问题,因为localStorage是html5的属性。
cookies实现浏览器内多个标签页(.html)之间的通信
1、reception.js接收页面
<div>
<span>收到消息:</span>
<span id="recMsg1"></span>
</div>
<div>
<span>收到消息:</span>
<span id="recMsg2"></span>
</div>
function getKey(key) {
var cookies = JSON.parse('{"' + document.cookie.replace(/=/g, '":"').replace(/;\s+/g, '", "') + '"}');
return cookies[key];
};
// 使用定时器轮巡获取数据
setInterval(function() {
recMsg1.innerHTML = getKey("msg1");
recMsg2.innerHTML = getKey("msg2");
}, 500);
2、send.js发送页面
<input id="msg1" type="text" />
<br />
<input id="msg2" type="text" />
<br />
<button id="send">发送</button>
send.onclick = function() {
// trim: 去除字符串的头尾空格
if (msg1.value.trim() !== "" && msg2.value.trim() !== "") {
document.cookie="msg1="+msg1.value.trim();
document.cookie="msg2="+msg2.value.trim();
}
};
3、注意
存在定时器问题。
webSocket实现浏览器内多个标签页(.html)之间的通信
1、缺点
1、需要服务端的支持才能完成任务。如果socket数据量比较大,会严重消耗服务起得资源。
2、必须要在服务端项目中写服务端监听程序才能使用。
2、优点
使用简单,功能灵活且强大,如果部署了webSocket服务器,可以实现很多实时通信功能。
3、步骤
第一步,新建一个文件夹webSocket。
第二步,初始化webSocket文件夹,使用npm init下载package.json文件。
第三步,使用npm install --save ws安装模块。
第四步,在webSocket文件夹里面创建三个文件,三个文件跟package.json文件同级,分别是:server.js/send.html/reception.html。
4、服务器端server.js文件代码
// 获得WebSocketServer类型
let WebSocketServer = require('ws').Server;
// 创建WebSocketServer对象实例,监听指定端口
let wss = new WebSocketServer({ port: 3600 });
// 创建保存所有已连接到服务器的客户端对象的数组
let clients = [];
// 为服务器添加connection事件监听,当有客户端连接到服务端时,立刻将客户端对象保存进数组中。
wss.on('connection', function(client) {
console.log("一个客户端连接到服务器");
if (clients.indexOf(client) === -1) {
clients.push(client);
console.log("有" + clients.length + "个客户端在线");
// 为每个client对象绑定message事件,
// 当某个客户端发来消息时,自动触发
client.on('message', function(msg) {
// console.log("收到消息:" + msg);
// 遍历clients数组中每个其他客户端对象,
// 并发送消息给其他客户端
for (let key of clients) {
if (key != client) {
key.send(msg);
}
}
});
}
});
// 启动服务器的命令node server.js
5、客户端send.html文件代码
<input type="text" id="msg">
<button id="send">发送</button>
// 建立到服务端websocket连接
let ws = new WebSocket("ws://localhost:3600");
send.onclick = function() {
if (msg.value.trim() !== "");
ws.send(msg.value.trim());
};
6、客户端reception.html文件代码
<div>
<span>收到消息:</span>
<span id="recMsg"></span>
</div>
// 建立到服务端websocket连接
let ws = new WebSocket("ws://localhost:3600");
// 当连接被打开时,
// 注册接收消息的处理函数
ws.onopen = function(event) {
// 当有消息发过来时,
// 就将消息放到显示元素上
ws.onmessage = function(event) {
recMsg.innerHTML = event.data;
};
};