cancel 回调是唯一可靠捕获遮罩层点击关闭的入口,它同时响应遮罩点击和右上角×按钮,适合统一做清理、状态回滚等操作;shadeClose: true 仅控制是否允许关闭,不提供独立回调。
shadeClose: true 只控制是否允许关闭,不提供回调入口
点击遮罩层触发关闭动作,但 shadeclose: true 本身不会执行任何 js 回调——它只是个开关。真正能捕获这个行为的,只有 cancel 回调函数,且它**同时响应右上角 × 按钮和遮罩层点击(当 shadeclose 启用时)**。
cancel 回调是唯一可靠捕获遮罩点击的时机
cancel 是 layer.open 配置中唯一能稳定覆盖遮罩层点击与关闭按钮两种路径的钩子。它在弹窗开始销毁前触发,适合做清理、状态回滚、取消请求等操作。
- 必须显式定义
cancel函数,否则点击遮罩或 × 都直接关闭,无干预机会 - 该函数接收两个参数:
index(弹窗索引)、layero(弹窗 DOM 元素),可用来判断来源(但 layer 未暴露点击源类型,无法区分是遮罩还是 ×) - 若需“仅遮罩点击才执行”,需自行监听遮罩层事件并阻止默认关闭,再手动调用
layer.close(index)——但会破坏原生逻辑,不推荐
为什么不能监听 .layui-layer-shade?
遮罩层(.layui-layer-shade)是全局插入的,多个弹窗共用一个遮罩(layer 2.8+ 默认复用),直接绑定 click 事件极易误触、重复绑定、漏解绑。
- 遮罩 DOM 在
success回调之后才存在,过早查询返回 null - layer 内部对遮罩点击做了
stopPropagation()和关闭逻辑封装,手动监听后调用layer.close()可能导致end或cancel重复触发 - 移动端 Safari 下遮罩层有时不响应
click,但touchstart又可能误判,兼容成本高
实际写法:在 cancel 中统一处理,必要时加标记
如果业务上真需要区分触发源(比如遮罩点击要统计埋点,而 × 点击不统计),可在打开弹窗时预先记录意图,或借助自定义属性临时标记:
var index = layer.open({
type: 1,
content: '<div>内容</div>',
shadeClose: true,
cancel: function(index, layero) {
// 所有关闭途径都走这里
console.log('弹窗即将关闭,index:', index);
// 做清理、取消 pending 请求、重置表单等
return true; // 允许关闭(默认行为)
}
});
注意:cancel 返回 false 可阻止关闭,但遮罩点击时 layer 仍会尝试关闭,行为不稳定;建议只做副作用处理,不要依赖返回值拦截。
cancel,没有更细粒度的原生 API。强行拆分来源,反而容易引发关闭不同步、事件竞争或移动端失效——老项目升级到 Layui 2.8+ 后尤其明显。











