同域下父页面可通过contentWindow直接调用子页面JS函数,但需确保iframe已加载完成且函数挂载到window全局;跨域则必须使用postMessage通信,并严格校验origin、时机和消息结构。

同域下父页面能直接调用子页面 JS 函数,关键在获取子页面的 window 对象;跨域则必须用 postMessage,硬连会失败。
用 contentWindow 获取子页面 window 对象
这是最常用、最直接的方式,但前提是 iframe 已加载完成且同域。如果 iframe 还没 ready 就调用,contentWindow 会是 null 或抛出跨域错误。
-
document.getElementById('myIframe').contentWindow是标准写法,兼容 Chrome/Firefox/Edge/Safari - IE8–10 支持
contentWindow,但 IE7 及更早需用contentDocument.defaultView - 别用
frames['name']或self.frames[0]—— 它依赖顺序或 name 属性,易错且不可靠 - 务必等
iframe.onload触发后再调用,否则contentWindow可能未就绪
确保子页面函数是全局可访问的
父页面拿到 contentWindow 后,调用的是子页面全局作用域下的函数。如果子页面用 const fn = () => {} 或 IIFE 包裹,函数不会挂到 window 上,父页面就找不到。
- 子页面中必须显式挂载:比如
window.childMethod = function() { ... }或直接function childMethod() { ... } - ES6 模块环境(如
type="module")下,函数默认不暴露,需手动赋值给window - Vue/React 单页应用里,子页面若没导出全局函数,父页面调用会报
TypeError: xxx is not a function
跨域时只能用 postMessage 通信
一旦父子页面协议、域名、端口任一不同,浏览器会阻止 contentWindow 访问,直接报错 Blocked a frame with origin "xxx" from accessing a cross-origin frame. 此时唯一合规方式是消息机制。
立即学习“前端免费学习笔记(深入)”;
- 父页面发送:
iframe.contentWindow.postMessage({type: 'callChildFn', payload: 'data'}, 'https://child-domain.com') - 子页面监听:
window.addEventListener('message', e => { if (e.origin !== 'https://parent-domain.com') return; ... }) - 注意:目标 origin 不能写
*(除非你真允许任意来源),否则接收方会忽略消息 -
postMessage是异步的,无法直接返回值,需要子页面再postMessage回传结果
最容易被忽略的是时机和作用域:没等 onload 就调用、子函数没挂到 window、跨域却硬试 contentWindow——这三类问题占了实际调试中 90% 的“调用失败”。



















