cancel是layui弹窗点击×或遮罩时唯一自动触发的必写回调,需显式定义;若要二次确认,首行必须return false阻断默认关闭,再调layer.confirm并手动close;ESC默认不触发cancel,需在success中监听keyup并手动调用。
cancel 回调就是点击取消按钮的唯一入口
点击右上角 × 按钮时,cancel 是 layui 唯一自动触发的回调函数,它不是可选配置项,而是必须显式定义才能捕获该行为。没写 cancel,点了 × 就直接关闭,无任何干预机会。
常见错误现象:
- 写了
cancel却没反应 → 检查是否设置了closeBtn: 0(隐藏了关闭按钮) - 弹窗闪一下又回来 →
cancel函数里漏了return false,但内部又执行了新弹窗或跳转,造成视觉错觉
正确写法示例:
layer.open({
content: '编辑表单',
cancel: function(index, layero) {
console.log('用户点了 ×');
// 这里做清理:重置表单、取消 pending 请求等
return true; // 允许默认关闭(这是默认行为,可省略)
}
});
想二次确认?必须开头 return false
cancel 不是“关闭前钩子”,而是“关闭动作已触发后”的回调。如果你在 cancel 里直接调 layer.confirm 却没先 return false,弹窗会先关掉,confirm 才弹出来——用户看到的就是一闪而逝。
关键操作顺序:
- 第一行必须写
return false,阻断默认关闭流程 - 紧接着调
layer.confirm,并在其yes和cancel回调里都显式调用layer.close(index) - 不能漏传
index,否则关错层或报错layer.close is not a function
示例:
layer.open({
content: '请确认',
cancel: function(index, layero) {
return false; // ⚠️ 必须放第一行
layer.confirm('确定要放弃修改?', function() {
layer.close(index); // 点确定才真关
}, function() {
layer.close(index); // 点取消也得关,否则残留
});
}
});
遮罩层点击和 × 按钮共用同一个 cancel
只要设置了 shadeClose: true,点击遮罩层也会触发 cancel 回调——它不区分来源,统一处理。这是 layui 的设计逻辑,没有单独的 “遮罩点击回调”。
所以别试图监听 .layui-layer-shade,原因很实际:
- 遮罩 DOM 是全局复用的,多个弹窗共用一个节点,绑定 click 容易误触
- layer 内部对遮罩点击做了
stopPropagation(),手动监听后调layer.close(index)可能导致end或cancel重复执行 - 移动端 Safari 下遮罩 click 事件有时不响应,
touchstart又容易误判,兼容成本高
真实做法:把所有“用户主动放弃”的逻辑(点 ×、点遮罩、甚至 ESC)都收口到 cancel 里统一处理。
ESC 键默认不走 cancel,需手动接管
按 ESC 关闭弹窗时,cancel 不会自动执行。因为 ESC 是通过全局 keyup 监听后直接调 layer.close(index) 实现的,绕过了 cancel 流程。
要让 ESC 行为和点 × 一致,必须在 success 回调里手动绑定并调用 cancel:
- 先保存传入的
cancel引用(避免匿名函数无法复用) - 在
success中监听document的keyup,判断e.which === 27 - 显式调用
userCancel(index, layero),再执行layer.close(index) - 务必在
end回调中解绑事件,否则内存泄漏
这个细节容易被忽略:没绑定 keyup,ESC 就只是“静默关闭”,所有清理逻辑都失效。


















