同源时直接操作window对象最省事,跨域时仅postMessage真正可用且安全;必须等iframe.onload后再调用contentWindow方法或postMessage,targetOrigin不可用'*',接收端须严格校验event.origin,子页监听需在DOMContentLoaded阶段注册,否则消息易丢失。

同源时直接操作 window 对象最省事,跨域时只有 postMessage 是真正可用且安全的方案;其他所谓“方式”要么已淘汰、要么有严重兼容或安全缺陷,实际项目里不该用。
同源 iframe 直接调用函数为什么必须等 onload
因为 iframe.contentWindow 在 DOM 解析完成但子页面 JS 还没执行完时可能为 null,或子页暴露的函数还没挂到 window 上。不等 onload 就调,大概率报 Cannot read property 'xxx' of null 或 xxx is not a function。
- 父页调子页:用
iframe.onload = () => { iframe.contentWindow.childInit(config) } - 子页暴露函数必须是全局的:
window.childInit = function(config) { ... },不能写在 IIFE 或模块里 - 避免用
document.frames['name']—— IE 专属,现代浏览器已移除支持
postMessage 的 targetOrigin 为什么不能写 '*'
targetOrigin 写 '*' 等于把消息广播给任意域名,任何中间人或恶意 iframe 都能监听并伪造响应。一旦父页逻辑依赖子页回传数据(比如登录态校验),就可能被劫持。
- 正确写法:
iframe.contentWindow.postMessage(data, 'https://child.example.com') - 子页接收时也必须严格比对:
if (event.origin === 'https://parent.example.com'),不能用includes()或正则匹配 -
event.data支持Object/Array/Date,但不传function、undefined、DOM node,否则静默丢弃
跨域通信时 message 监听器注册太晚会丢消息
postMessage 是异步发送的,但不保证接收方一定能收到 —— 如果子页的 message 监听器还没注册,那第一条消息就永远丢失。SPA 页面路由切换后还可能重复绑定,导致同一事件触发多次。
立即学习“前端免费学习笔记(深入)”;
- 子页必须在
<script>标签顶部或DOMContentLoaded阶段就注册:window.addEventListener('message', handler) - 父页发消息前先检查:
if (iframe.contentWindow) iframe.contentWindow.postMessage(...),否则报Cannot read property 'postMessage' of null - 需要响应的场景,建议加超时重试 + 唯一
messageId,别指望一次postMessage就稳收
最容易被忽略的是时序问题:不是“写了 postMessage 就算通了”,而是“谁先加载完、谁先注册监听、谁先发、谁处理响应”,四个环节缺一不可。哪怕只漏掉一个 onload 或一个 addEventListener,通信就断在看不见的地方。



















