父页面变量需挂载到window上且确保子iframe加载时已存在,子页应通过window.parent访问并加判空;跨域时必须用postMessage通信,避免直接读取变量或依赖getChildFrame获取JS上下文。
父页面变量怎么让子 iframe 页面读到
必须挂到 window 上,且子页加载时它得已存在。layui 的 type: 2 弹层本质是 iframe,子页脚本执行时若父页变量还没定义,window.parent.xxx 就是 undefined。
- 父页要写成
window.currentUser = { id: 123, name: 'admin' },不能只写const currentUser = {...} - 子页别在
<script></script>顶层直接读,加一层判断:if (window.parent && window.parent.currentUser) { ... } - 更稳妥的做法:父页在
success回调里等 iframe 加载完再发数据,比如用iframe.contentWindow.postMessage(...) - 常见报错
Cannot read property 'xxx' of undefined,90% 是变量没挂window或执行顺序错了
子页面怎么把值传回父页面
最稳的方式是父页提前声明一个全局函数,子页调用它并传参,而不是试图读取子页内部变量或依赖 layer.getChildFrame。
- 父页必须定义类似
window.setSelectData = function(data) { console.log(data); },且不能包在$(document).ready或异步回调里 - 子页点击确定时写:
if (typeof parent.setSelectData === 'function') { parent.setSelectData({ id: 1001 }); } - 紧接着关闭弹层:
var index = parent.layer.getFrameIndex(window.name); parent.layer.close(index); - 别用
window.opener——Layui 弹层不是新窗口,window.opener永远是null
跨域时变量共享完全失效怎么办
只要协议、域名、端口任一不同,window.parent 访问立刻被浏览器拦截,报 Blocked a frame with origin ... from accessing a cross-origin frame。这时候没有绕过方案,只能换通信方式。
- 唯一通用解法是
postMessage,父页发、子页监听,或反过来 - 子页发消息给父页:
parent.postMessage({ type: 'SELECTED', data: item }, 'https://your-domain.com')(第二个参数不能写*,必须指定确切 origin) - 父页监听:
window.addEventListener('message', e => { if (e.origin !== 'https://child-domain.com') return; ... }) - IE8–9 不支持
postMessage,真要兼容就得降级用 URL hash 轮询——但不推荐,维护成本高、易出竞态
为什么 success 回调里用 getChildFrame 读不到子页 JS 变量
layer.getChildFrame 返回的是 jQuery 对象(对应子页 DOM),不是子页 JS 执行上下文。它能操作表单、填值,但没法读 var foo = 'bar' 这种局部变量。
- 想预填子页 input?可以:
iframe.find('input[name="id"]').val(initId) - 想读子页计算后的结果?不行。子页必须主动通知父页,比如点击按钮后调用
parent.callback(...)或发postMessage -
window.name不稳定,别依赖它获取 iframe 索引;getFrameIndex更可靠,但前提是子页已加载完成 - 子页 JS 执行时机不可控,尤其带 AJAX 初始化的场景——父页
success触发时,子页可能连<script></script>都没执行完
console.log,别只盯着语法对不对。











