前言
公司后台项目微前端是使用iframe方式,跨页面通讯postMessage就需要我们必须掌握。比如,弹窗页与父页面的数据同步、多个标签页间的状态共享、嵌入的iframe与宿主页面的交互等。
本文将从基础原理到实战场景,全面解析 postMessage 的用法,帮你轻松搞定各类跨页面通讯需求。
先看一张总结图,了解通讯的几种场景:

1. 什么是postMessage
postMessage 是用于在不同源的窗口、iframe、Worker之间安全地传递数据。打破了浏览器的"同源策略"限制,让跨源页面之间能够实现数据传递和事件通信。
postMessage 的使用逻辑非常简单,分为"发送数据"和"接收数据"两个步骤,本质是基于"消息发布-订阅"模式。
1.1 发送数据:targetWindow.postMessage()
发送数据的操作由"发送方窗口"调用 postMessage 方法完成,该方法挂载在窗口对象(window)上,语法如下:
ini
targetWindow.postMessage(message, targetOrigin, [transfer]);
参数的含义和使用要点:
- targetWindow(必选) :接收消息的目标窗口对象,即"谁要接收这个消息"。常见的获取方式有: iframe的contentWindow:
document.getElementById('iframeId').contentWindow(父页向子页发消息); - window.opener:通过
window.open()打开的新窗口,其内部通过opener获取父窗口(子页向父页发消息); - window.parent:iframe内部通过
parent获取父窗口(子页向父页发消息); - message(必选) :要发送的数据,可以是字符串、数字、对象、数组等几乎所有类型。但需要注意: 数据会被隐式序列化为JSON格式传递,接收方需要自行解析(部分浏览器会自动反序列化,但建议显式处理以兼容);
- 避免发送过大的数据(如超过10MB),可能导致性能问题或传输失败。
- targetOrigin(必选) :目标窗口的"源"(协议+域名+端口),用于安全校验,即"只有该源的窗口才能接收消息"。取值规则: 具体源:如
'https://www.example.com:8080',仅该源的窗口能接收; - 通配符
'*':允许所有源接收消息(极度危险,仅开发测试时临时使用); - 空字符串
'':仅适用于发送给file://协议的窗口(实际开发中极少用)。 - transfer(可选) :是一个包含可转移对象的数组,这些对象的所有权会从发送方转移到接收方,发送方后续无法再使用这些对象(如ArrayBuffer)。该参数使用场景较少,一般无需关注。
1.2 接收数据:监听 message 事件
接收数据的窗口需要监听自身的message事件,当有其他窗口通过postMessage发送消息时,该事件会被触发。语法如下:
javascript
window.addEventListener('message', (event) => {
// 处理接收的消息
}, false);
核心是解析事件对象event的三个关键属性:
- event.data :发送方传递的消息数据(即
postMessage的第一个参数); - event.origin:发送消息的窗口的"源"(协议+域名+端口),用于校验发送方身份;
- event.source:发送消息的窗口对象,可用于向发送方回传数据。
接收方必须通过event.origin校验发送方的合法性,避免接收恶意源发送的消息,这是与targetOrigin对应的双重安全保障。
2. 实战案例:同页面iframe通讯
父页面嵌入iframe,两者需要实现数据交互(如父页向子页传用户信息,子页向父页传操作结果)。
2.1 父->子
发送端(父页面):
js
// 发送到指定 iframe
iframe1.contentWindow.postMessage({
from: 'Parent (父页面)',
message: '消息内容'
}, '*');
接收端(子页面):
js
// 在 Vue 组件中监听消息
window.addEventListener('message', function(event) {
});
接收的数据:

2.2 子->父
发送端(子页面):
js
// 从子页面发送消息到父页面
window.parent.postMessage({
target: 'parent',
from: 'Home (iframe1)',
message: '消息内容'
}, '*');
接收端(父页面):
js
// 父页面监听消息
window.addEventListener('message', function(event) {
if (event.data.target === 'parent') {
console.log('父页面处理消息:', event.data.message);
// 在页面上显示日志
}
});
父接收数据:

2.3 兄弟
对于兄弟页面,无法通过postMessage直接通讯,只能通过父页面进行中转,可以根据特定的类型,让父元素进行转发。具体不作介绍。
3. 实战案例:window.open打开方式通讯
通过window.open()打开新窗口后,父页可通过返回的窗口对象发送消息,子页通过window.opener获取父页窗口。
3.1 父->子
发送端(父页面):
js
const child = window.open(url)
child.contentWindow.postMessage({
from: 'Parent (父页面)',
message: '消息内容'
}, '*');
接收端(子页面):
js
window.addEventListener('message', function(event) {
});
3.2 子->父
发送端(子页面):
js
// 从子页面发送消息到父页面
window.opener.postMessage({
message: '消息内容'
}, '*');
接收端(父页面):
js
// 父页面监听消息
window.addEventListener('message', function(event) {
});
3.3 兄弟
对于兄弟页面,无法通过句柄直接进行通讯,因为对于各自单独打开的页面,没法获取到窗口的句柄,也就没法进行消息的发送和监听。只能通过父页面进行中转,可以根据特定的类型,让父元素进行转发。具体不作介绍。
总结
最后总结一下:postMessage通过targetWindow.postMessage发送数据,其中targetWindow可以是iframe 的 contentWindow 属性或者执行window.open返回的窗口对象,通过监听message事件接收消息。
下一篇,我们将了解前端跨页面通讯的其他方案Broadcast Channel。
如有错误,请指正O^O!