聊聊页面间的通信机制

在浏览器中会涉及到一些跨页面的通信来完成一些特定的业务逻辑,下面梳理下一些跨页面通信相关的技术点。

postMessage

postMessage用法解释

ini 复制代码
otherWindow.postMessage(message, targetOrigin, [transfer]);
  • • otherWindow 其他窗口的引用,比如iframe的contentWindow、执行window.open的返回的窗口对象、window.parent获取的父窗口对象。利用window.open返回的窗口对象可以实现跟新窗口的通信
  • • message 需要发送的数据,它会被结构化克隆算法序列化,无法被结构化克隆的数据会导致异常或者丢失属性,比如函数/原型链的丢失等
  • • targetOrigin 指定哪些源可以接收数据,这里就可以实现跨源的通信和安全控制
  • • transfer 可选的Transferable对象

父子窗口通信

父窗口发送消息给子窗口

在父窗口通过获取子iframe的conentWindow获取子窗口的引用,调用postMessage方法就可以实现对子窗口发送消息

javascript 复制代码
// 父窗口发送消息
iframe.contentWindow.postMessage('message from parent', '*')

// 子窗口监听消息
window.addEventListener('message', function(event) {
    // 处理接收到的消息
    console.log(event.data);
});

子窗口发送消息给父窗口

子窗口通过window.parent获取父窗口的引用,调用postMesage方法就可以实现对父窗口发送消息

javascript 复制代码
// 子窗口发送消息
window.parent.postMessage('message from child', '*')

 // 父窗口监听消息
window.addEventListener('message', function(event) {
    // 处理接收到的消息
    console.log(event.data);
});

浏览器不同tab间通信

跨tab通信有可能涉及到不同tab的数据同步逻辑,是一个相对常见的场景

localStorage

sessionStrage在chrome中打开同源的tab时候不会共享sessionStorage,所以主要介绍localStorage的实现方案.localStorage是在同域名下共享的浏览器存储,在同域的不同tab下监听localStorage的storage事件就可以实现跨tab通信

javascript 复制代码
// 在第一个标签页中设置数据到 sessionStorage 中
sessionStorage.setItem('message', 'Hello from Tab 1!');

// 第二个标签页也打开当前页面 监听 storage 事件 接收其他标签页的数据
window.addEventListener('storage', function(event) {
    if (event.key === 'message') {
        console.log('Received message in Tab 1:', event.newValue);
    }
});

WebSocket

这种方案依赖需要依赖服务服务端

javascript 复制代码
// 建立websocke连接
const socket = new WebSocket("ws://localhost:8080");

// 连接建立,跟服务端发送事件,服务端对所有连接的websocket client广播事件
socket.addEventListener("open", function (event) {
    socket.send("Hello Server!");
});

// 接收事件消息
socket.addEventListener("message", function (event) {
    console.log("Message from server ", event.data);
});

使用websocket这种方案相对重,除非已有websocket长连接并且需要考虑websocket的断连造成的通信失败

BroadcastChannel

BroadcastChannel可以做到同源窗口间的通信能力.它基于发布-订阅的模式实现消息通知。

javascript 复制代码
// 发送方逻辑
// 创建BroadcastChannel 在实现跨tab通信的时候,创建BroadcastChannel的channelName需要是一个
const channel = new BroadcastChannel('myChannel');

// 发送消息到其他标签页 
channel.postMessage('Hello from Tab 1!');

// 监听方逻辑
// 创建BroadcastChannel 与发送方channelName一致
const channe2 = new BroadcastChannel('myChannel');
// 监听消息
channe2.onmessage = function(event) {
    console.log('Received message in Tab 2:', event.data);
};

Service Worker/SharedWorker

Service Worker和SharedWorker方案类似,都是运行worker实现消息通信,下面主要举例SharedWorker的实现方案。

定义worker脚本

javascript 复制代码
// shared-worker.js
// 定义一个变量来保存所有连接的客户端
let clients = [];

// 监听连接事件
self.addEventListener('connect', function(event) {
    // 获取与该连接关联的端口
    const port = event.ports[0];

    // 将端口添加到客户端列表中
    clients.push(port);

    // 监听来自客户端的消息
    port.addEventListener('message', function(event) {
        // 广播消息给所有其他客户端
        clients.forEach(function(client) {
        if (client !== port) {
            client.postMessage(event.data);
        }
        });
    });

    // 监听客户端关闭事件
    port.addEventListener('close', function() {
        // 从客户端列表中移除关闭的端口
        clients = clients.filter(function(client) {
        return client !== port;
        });
    });

    // 向客户端发送连接成功消息
    port.postMessage('Connected to SharedWorker.');
});

页面中加载脚本

javascript 复制代码
    // 在你的网页中连接到 SharedWorker
    const worker = new SharedWorker('shared-worker.js');

    // 监听连接成功事件
    worker.port.addEventListener('message', function(event) {
        console.log('Received message:', event.data);
    });

cookies

这种方案不大推荐,涉及到js可以通过脚本对cookies进行读写

欢迎大家关注我的微信公众号: 前端小板凳

相关推荐
一个儒雅随和的男子几秒前
Web开发身份认证技术解析
前端·github
小二·1 分钟前
DevUI 和 MateChat:2025 年,我们是怎么把前端开发变轻松的
开发语言·javascript·vue.js
G***E3164 分钟前
前端自动化测试工具:8个主流方案对比
前端·测试工具·自动化
●VON13 分钟前
基于 Electron 模拟鸿蒙设备硬件信息查询的可行性探索
javascript·学习·electron·openharmony
一 乐17 分钟前
游戏账号交易|基于Springboot+vue的游戏账号交易系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端·游戏
西洼工作室20 分钟前
前端自制设备模拟器模拟不同终端展示效果
前端·css3·js·响应式开发
ByteCraze24 分钟前
面向Nodejs开发人员MCP快速入门
前端·node.js·agent·mcp
chéng ௹24 分钟前
前端转编码(encodeURIComponent)以及解码(decodeURIComponent)
开发语言·前端·javascript
温轻舟34 分钟前
禁毒路上,任重道远 | HTML页面
开发语言·前端·javascript·css·html·温轻舟
likuolei1 小时前
XSL-FO 列表
前端·数据库