Layui 的 layer.open 通过 type: 2 和 content 传 URL 字符串自动创建 iframe,不可传 HTML;监听加载需在 success 回调中获取原生 iframe 元素并绑定 onload;跨域通信须用 postMessage。
layer.open 怎么用 iframe 属性加载页面
直接传 type: 2 并指定 content 为 url 字符串,layui 就会自动创建 iframe。不需要手动拼 dom 或写 <iframe></iframe> 标签。
常见错误是把 content 写成 HTML 字符串(比如 '<iframe src="..."></iframe>'),这会导致 iframe 被当作文本渲染,无法加载或监听事件。
-
type: 2是关键,不是默认值(默认是type: 0,即纯文本) -
content必须是字符串 URL,例如'/admin/user/edit?id=123' - 不要加
target="_blank"或其他属性,Layui 内部会处理 iframe 的 sandbox 和 referrer 策略
如何监听 iframe 加载完成(onload)
Layui 没有暴露原生 iframe.onload 的回调入口,但提供了 success 回调函数——它在 layer DOM 插入页面后触发,此时 iframe 元素已存在,但未必加载完成。
真正可靠的监听方式是:在 success 里拿到 iframe 元素,再绑定其 load 事件。注意必须用原生 addEventListener 或 onload 属性,jQuery 的 .on('load') 在某些版本中对 iframe 不生效。
- 用
success获取弹层容器:var iframe = layer.getChildFrame('iframe', index).get(0) - 或者更稳妥:先查
$('.layui-layer-content iframe'),再取[0]原生节点 - 绑定
iframe.onload = function() { ... },不要用$(iframe).on('load', ...) - 如果 iframe 页面跨域,
load仍会触发,但无法读取其contentDocument—— 这是浏览器限制,不是代码问题
为什么 load 事件有时不触发或触发两次
本质原因是 iframe 的 src 被重复设置,或页面存在缓存重定向(如 HTTP 304、302),导致浏览器认为“资源已加载”,跳过 onload。
典型场景:后台返回 302 跳转到登录页,或前端 URL 拼接时漏了问号,变成 /page?&id=1 这类非法参数,服务端返回空响应或重定向。
- 检查 Network 面板,确认 iframe 请求状态码是 200 且响应体非空
- 避免动态修改 iframe
src:Layui 创建后不要手动赋值iframe.src = '...',否则会再次触发 load - 若需刷新 iframe,用
location.reload()或重新 open,而不是改 src - IE 下可能需兼容
readyState === 'complete',但 Layui 官方已放弃 IE 支持,可忽略
怎么从父页面向 iframe 传参或调用方法
不能依赖 window.frames[i] 索引,因为 layer 可能嵌套、多实例并存。正确做法是通过 iframe 的 contentWindow 安全访问(前提是同源)。
加载完成后,可用 iframe.contentWindow.xxxFunction() 调用子页面方法;子页面可通过 window.parent.layer 或自定义事件通知父页。
- 确保子页面已定义全局函数,如
window.initData = function(data) { ... } - 在 onload 里执行:
iframe.contentWindow.initData({ id: 123 }) - 子页面发消息给父页:
window.parent.postMessage({ type: 'save-success' }, '*') - 父页监听:
window.addEventListener('message', e => { if (e.data.type === 'save-success') { layer.close(index) } })
跨域场景下只能靠 postMessage,别试图读写 contentDocument,会报 SecurityError。











