同源时直接用 contentWindow 调方法或赋值最简单;跨域时唯一安全、可靠的方式是 postMessage。同源需协议、域名、端口完全一致,且须等 iframe.onload 后操作;跨域必须指定精确 targetOrigin 并校验 event.origin,监听器需尽早注册以防消息丢失。

同源时直接用 contentWindow 调方法或赋值最简单;跨域时唯一安全、可靠的方式是 postMessage,其他任何尝试(比如改 src 拼参、读 contentDocument)都会在现代浏览器中失败或被拦截。
同源场景:用 contentWindow 直接调用子页函数或变量
前提是父页和 iframe 的协议、域名、端口三者完全一致。此时你可以把子页当成本地模块来操作。
- 必须等
iframe.onload触发后再访问contentWindow,否则contentWindow可能为null,或子页函数还没定义 - 推荐写法:
iframe.contentWindow.updateParam("hello"),其中updateParam是子页全局函数(不能是闭包内或模块作用域里的) - 也可以直接赋值:
iframe.contentWindow.myData = { id: 123, name: "test" },子页在window.myData里取 - 不要用
document.frames['name']—— IE 专属,已废弃,现代浏览器不支持
跨域场景:必须用 postMessage,且 targetOrigin 不能写 "*"
postMessage 是 HTML5 唯一被所有现代浏览器支持的跨域通信机制,它不绕过同源策略,而是由浏览器做 origin 校验后转发。
- 父页发送前先检查:
if (iframe.contentWindow) iframe.contentWindow.postMessage({ type: "init", data: "xxx" }, "https://child.example.com") -
targetOrigin必须精确指定,如"https://child.example.com";写"*"会让任意站点伪造 origin 接收消息,存在 XSS 风险 - 子页监听时必须校验
event.origin:if (event.origin !== "https://parent.example.com") return;不能用includes或正则模糊匹配 -
event.data支持Object、Array、Date等结构化克隆类型,但不支持function、undefined、DOM node
想“初始化就传参”?别拼 URL,要靠时机控制
有人习惯在 src 后加 ?key=value 传参,这看似简单,但有硬伤:子页无法确认参数是否被父页“有意传递”,也无法响应式反馈;更关键的是,如果子页是 SPA(比如 Vue/React),路由变化后 URL 参数还在,但逻辑可能已失效。
立即学习“前端免费学习笔记(深入)”;
- 正确做法是:父页在
iframe.onload后立即postMessage,子页在DOMContentLoaded或script最顶部注册message监听器 - 子页若需确保首次加载就收到消息,监听器必须早于任何业务逻辑注册,不能等到某个按钮点击才绑定
- 如果子页需要返回确认,应设计成“发消息 → 监听回传”,而不是单向假设
最容易被忽略的是时序问题:消息不是发了就一定被收到。子页可能还没执行到 addEventListener("message", ...),父页就发了第一条消息——它会彻底丢失。所以 onload 和监听器注册的位置,比你写的参数内容更重要。



















