跨协议或跨端口时浏览器强制拦截 window.parent 访问,因违反同源策略;唯一可行方案是 postMessage 通信,需严格校验 origin、确保监听在顶层窗口,并安全检查依赖对象是否就绪。
跨协议(如 http 与 https)或跨端口(如 :8080 与 :3000)时,浏览器会强制拦截 window.parent 访问,直接报 blocked a frame with origin ... from accessing a cross-origin frame —— 这不是 layui 的 bug,是浏览器安全策略铁律,无法绕过,只能换通信方式。
为什么 parent.xxx() 一调就报错?
因为父子页面协议、域名、端口三者任一不同,即触发跨域。此时 window.parent 对象存在,但它的属性和方法全部被浏览器屏蔽,读取任何字段都会抛出 DOMException。即使只是 console.log(parent),展开时也会卡住或报错。
-
parent.submitForm→undefined(不是没定义,是被拒绝访问) -
typeof parent.submitForm === 'function'→false(实际是"undefined",但 typeof 不报错) -
parent.postMessage仍可用,但必须指定明确origin,不能用'*'
必须用 postMessage + 监听,且 origin 不能写错
这是唯一能跨协议通信的方案。关键不是“怎么发”,而是“谁监听”和“校验是否可信”。
- 子页面发消息:必须用
parent.postMessage({type: 'SAVE_SUCCESS', data: result}, 'https://your-domain.com')——origin必须精确匹配父页协议+域名+端口,写成'*'在现代浏览器中会被静默丢弃 - 父页面监听必须挂载在顶层窗口:如果父页本身嵌在另一个 iframe(如 LayuiAdmin 的 tab 页),
window.addEventListener('message', ...)要写在最外层 layout 页面,而不是某个子 tab 里 - 监听函数里第一件事是校验
e.origin:如果e.origin !== 'https://your-domain.com',直接return,否则可能被恶意 iframe 欺骗 - 子页面发消息前,先确认
parent !== window且parent.postMessage存在,避免在非 iframe 环境下报错
父页面如何安全接收并响应?
接收后别直接执行逻辑,先解构、再校验、最后触发业务动作。尤其注意:不要在 message 回调里直接调 tableIns.reload(),除非你确定 tableIns 已初始化。
- 用
typeof tableIns !== 'undefined' && typeof tableIns.reload === 'function'双重判断,防止父页表格还没渲染完就调用 - 如果需要刷新带参数(如跳转第一页),把参数放在 postMessage 的
data字段里:{type: 'REFRESH', page: 1, filter: {status: 'active'}} - 子页面发完消息后,应立刻关闭自己:
parent.layer.close(parent.layer.getFrameIndex(window.name))—— 注意这里用的是parent.layer,不是window.layer - 父页面收到消息后,不建议立即
location.reload();优先走局部刷新,比如tableIns.reload({page: {curr: 1}})
真正难的不是写几行 postMessage,而是确保父子两端的 origin 完全一致、监听位置在顶层、且所有依赖对象(如 tableIns)已就绪。跨协议场景下,连 window.parent.layui 都拿不到,更别说直接调函数——这时候硬写 parent.xxx() 只会让控制台越来越红。


















