必须在layer.open()的end回调中解绑window.resize监听,使用removeEventListener或AbortController;禁止在cancel/beforeClose或success中解绑,避免重复绑定、样式抖动或脚本卡死。

当Layui弹窗中手动绑定了window.resize事件用于动态调整尺寸或居中,若不及时解绑,多次打开弹窗会导致监听函数重复注册,最终引发性能下降、样式抖动甚至脚本卡死。
关闭前主动解绑resize监听
在layer.open()配置中使用end回调——这是唯一能确保DOM已销毁、JS上下文即将退出的时机,适合做清理工作。
第一步:声明一个全局或闭包内可访问的resizeHandler函数,并用let定义其引用变量,避免无法覆盖。
第二步:在success回调里绑定window.resize,同时将handler存入变量;注意必须用layui.util.throttle节流,否则高频触发会直接拖垮页面。
第三步:在end回调中调用window.removeEventListener('resize', resizeHandler)。这一步不能省略,也不能写成$(window).off('resize', ...)——jQuery.off对原生addEventListener绑定的监听无效。
更稳妥的解绑方式(推荐)
方法一:用AbortController配合addEventListener的{ signal }选项(现代浏览器支持,Chrome 66+/Firefox 63+/Edge 79+)
在layer.open()前创建const controller = new AbortController();,并在success中绑定:window.addEventListener('resize', handler, { signal: controller.signal });。然后在end里直接执行controller.abort(),浏览器自动解绑所有关联监听器。
方法二:为监听器打标记并统一管理
定义一个弱映射表const resizeHandlers = new WeakMap();,每次open时以layero[0]为key存入handler;end中取出并解绑。这样即使同一页面多个弹窗也不会互相干扰。
【必须检查layero是否存在且未被销毁】:在end里先判断layero && layero[0],否则layero.find('iframe')等操作会报错中断后续清理逻辑。
常见错误写法及后果
在cancel或beforeClose里解绑——这些回调触发时DOM仍存在,用户若取消关闭(比如beforeClose返回false),监听器已被删,但窗口还在,后续resize就完全失效。
把removeEventListener写在success里——还没绑定完就解绑,等于白写。
用$(window).on('resize', ...)绑定却用$(window).off('resize')解绑——如果页面其他模块也用jQuery绑了resize,这一刀会误杀全部,引发不可预知的UI异常。











