应使用 type: 1 + 手动插入 iframe 并监听 onload 事件配合 layer.load()/closeLoad() 实现加载提示;跨域时不可靠,同源推荐 fetch 替代 iframe 以精准控制加载状态。
layer.open 加载外部 URL 时默认不显示进度条
layui 的 layer.open 在 type: 2(iframe 层)下加载外部 url,本身不提供内置进度条;它只在 type: 1(页面层)配合 content: '' + 手动加载时才容易介入 dom。所以想“在 iframe 加载过程中显示进度条”,得绕过 layer 自动 iframe 插入逻辑,改用手动控制。
用 type: 1 + iframe 手动插入实现可监听的加载流程
核心思路是:不用 type: 2,改用 type: 1,自己创建 <iframe></iframe> 元素,监听其 onload 事件,并在加载中显示遮罩或进度提示。layer 提供了 layer.load() 和 layer.closeLoad() 配合使用。
- 先调用
layer.load(2)显示转圈加载图标(2 表示风格) - 再用
layer.open({ type: 1, content: '<iframe src="..."></iframe>' })打开弹层 - 在 iframe 的
onload回调里调用layer.closeLoad() - 注意:iframe 必须同源才能可靠触发
onload;跨域时 onload 可能静默触发或不触发,且无法读取 iframe.contentDocument
示例代码片段:
layer.load(2);
layer.open({
type: 1,
title: '加载中...',
area: ['800px', '600px'],
content: '<iframe src="https://example.com/page.html" style="width:100%;height:100%;border:none;" onload="layer.closeLoad()"></iframe>'
});
更稳的方式:用 fetch + innerHTML 替代 iframe(适合同源页面)
如果目标 URL 是你自己的同源页面(如 /admin/user/list),推荐不用 iframe,改用 fetch 获取 HTML 片段,再注入到 type: 1 弹层中。这样能完全掌控加载状态,也避免 iframe 样式隔离、脚本执行受限等问题。
-
fetch成功后,用response.text()拿到 HTML 字符串 - 提取关键内容(比如只取
内部或某个id="container"的部分),避免引入重复 CSS/JS - 注入前调用
layer.closeLoad(),失败时用layer.msg('加载失败') - 注意:原页面里的相对路径(如
./css/app.css)会失效,需提前转为绝对路径或服务端处理
为什么不要给 iframe 加 loading="eager" 或用 JS 模拟进度条?
浏览器对 iframe 的加载没有提供类似 XMLHttpRequest.upload.onprogress 的事件;loading="eager" 是预加载提示,不影响渲染行为,也无法触发回调。网上有些方案用定时器 + iframe.contentDocument 判空来“模拟”进度,但既不准又不可靠——尤其在 iframe 还没完成文档解析时,访问 contentDocument 会报错 Access to iframe.contentDocument is denied(跨域)或返回 null(未就绪)。
真正可控的加载反馈,只存在于你发起请求的那一刻(fetch / xhr)和收到响应的那一刻。iframe 是黑盒,layer 不暴露底层实例,强行 hack 容易在 layui 升级后失效。











