必须同时设置prop('disabled', true)和layui-btn-disabled类才能真正禁用按钮,仅设属性或仅加类均无效;表单提交需先校验再禁用,AJAX后在always中恢复;表格行内按钮须配合数据守卫;弹层倒计时需在success回调操作并管理timeoutId;移动端优先监听touchstart;可靠禁用依赖模板、事件守卫、请求生命周期三层绑定。

点击后立即禁用按钮必须同时操作 prop('disabled', true) 和 layui-btn-disabled 类
只设 disabled 属性或只加类,按钮都会“看起来灰了但还能点”。Layui 的事件是委托到容器上的,原生 disabled 不会阻断冒泡,lay-event 仍会触发。必须双管齐下:
-
$(this).prop('disabled', true)—— 阻断原生交互和表单链路(attr不可靠,部分浏览器不生效) -
.addClass('layui-btn-disabled')—— 同步灰显样式,否则视觉无反馈 -
.text('提交中…')—— 明确提示状态,避免用户困惑或重复点击
表单提交场景下禁用时机必须卡在 form.on('submit') 开头
验证逻辑不能晚于禁用动作,否则可能跳过校验;也不能早于验证,否则异步验证(如用户名查重)还没返回就锁死了 UI。正确顺序是:
- 先执行
form.verify()或手动校验逻辑 - 校验通过后,立刻
$(this).prop('disabled', true).addClass('layui-btn-disabled').text('提交中…') - 再发 AJAX 请求,且必须在
$.ajax().always()或complete中恢复按钮,覆盖 success / error / timeout 所有路径
漏掉 always 是常见卡死原因:请求失败后按钮一直不可点,用户只能刷新页面。
表格行内按钮点击后禁用要配合事件守卫,不能只信 DOM 状态
用户可能用 DevTools 删掉 layui-btn-disabled 类,或直接调 obj.tr.querySelector('[lay-event="edit"]').click() 绕过模板判断。所以:
- templet 中禁用只是第一道 UI 层面的过滤,仅用于提示
- 所有
table.on('tool(filter)', ...)回调开头必须加数据守卫:if (obj.data.status !== 'active') return; - 不要查按钮 DOM:
$(obj.tr).find('button').prop('disabled')—— 表格重载后这个值完全不可信 - 状态判断逻辑建议抽成函数,比如
canEdit(obj.data),方便复用和测试
弹层里倒计时禁用需在 success 回调中操作并管理 timeoutId
layer.open() 是异步的,DOM 渲染完成前查不到按钮。必须等 success(layero, index) 才能安全定位:
- 用
$(layero).find('button[lay-filter="save"]'),别用全局选择器,避免误操作其他弹层 - 在
setTimeout前声明let timeoutId,并在按钮点击、弹层关闭(cancel)时调clearTimeout(timeoutId) - 移动端优先监听
touchstart,防止 300ms 延迟导致重复触发
真正可靠的禁用,永远落在模板渲染 + 事件回调守卫 + 请求生命周期绑定这三层上,缺一不可。DOM 层面的手动操作只是临时补丁,reload 后全丢,别当主力方案。


















