必须在关闭弹窗前手动暂停并移除video元素或调用播放器dispose方法,否则Safari等浏览器会阻塞layer销毁流程导致遮罩残留;iframe内视频需通过postMessage通知暂停。
layer.open 后 video 元素阻止弹窗关闭
弹出层里嵌了 <video> 标签,点击右上角 × 或调用 layer.close(index) 时弹窗“卡住”——视觉上消失但遮罩层残留、页面无法操作。根本原因是部分浏览器(尤其是 safari 和某些 android webview)在 <video> 播放中会阻止父容器的 dom 移除或隐藏,layer 的销毁流程被阻塞。
常见触发场景:
-
<video autoplay>自动播放未加muted - 视频正在缓冲或处于
playing状态时直接关闭弹窗 - 使用了第三方播放器(如 video.js、DPlayer)但未手动销毁实例
关闭前必须手动 pause + removeChild
不能依赖 layer 自动清理。必须在 yes、cancel 或显式关闭逻辑中,先操作视频元素本身。
实操建议:
- 给
<video>加id="myVideo"或用 class 定位,确保能拿到 DOM 引用 - 在关闭前执行:
document.getElementById('myVideo').pause(); - 再移除节点:
document.getElementById('myVideo').remove();(比display: none更彻底) - 若用了 video.js:
player.dispose();必须调用,否则内部事件监听器残留
示例片段:
layer.open({
content: '<video id="myVideo" src="/video.mp4" controls></video>',
yes: function(index, layero) {
const video = document.getElementById('myVideo');
if (video) {
video.pause();
video.remove();
}
layer.close(index);
}
});
iframe 层里嵌视频的特别处理
如果弹窗是 type: 2(即 iframe),且视频在 iframe 页面内,layer.close() 不会自动触发 iframe 内的 pause()。这时需跨域通信或提前约定销毁协议。
安全可行的做法:
- 在 iframe 页面内监听
window.parent的自定义事件:window.addEventListener('message', e => { if (e.data === 'close-video') video.pause(); }); - 在主页面关闭前发消息:
iframe.contentWindow.postMessage('close-video', '*'); - 避免用
srcdoc或内联 HTML 嵌 iframe 视频,这类写法在 iOS 上极易触发静音策略导致播放异常,进而影响关闭流程
移动端真机上关闭按钮点不中的隐性原因
不是 JS 问题,而是视频控件层叠在关闭按钮上。尤其在 iPhone X/XS 等刘海屏,<video> 默认全屏按钮、控制栏会覆盖右上角区域,导致点击穿透失败。
解决方向:
- 关闭视频默认控制栏:
<video controls="false">,改用自定义按钮 - 给弹窗加
maxWidth: '100%'和area: ['90%', 'auto'],避免宽度撑满后控制栏挤压关闭按钮 - 关键:在
success回调里重置按钮 z-index ——$('.layui-layer-close').css('z-index', 999999);,因为视频控件可能动态提升自身层级
真正难缠的从来不是 layer.close() 调用失败,而是视频元素在底层悄悄 hold 住了整个销毁链路。不手动干预生命周期,光靠 layer API 是关不干净的。



















