layui按钮禁用需同时设置disabled属性和layui-btn-disabled类,禁用时机应在验证通过后、ajax发出前,移动端优先在touchstart阶段处理,并在ajax的always回调中统一恢复。
提交按钮禁用必须同时操作 dom 属性和 css 类
只加 disabled 属性或只加 layui-btn-disabled 类都不够——前者没视觉反馈,后者仍可点击。layui 按钮禁用需双管齐下:disabled 阻断事件,layui-btn-disabled 同步灰显样式。
常见错误是仅写 $('#submitBtn').attr('disabled', true),结果按钮变灰失败,用户还能点;或者只加类,但没设 disabled,导致点击后仍触发 form.on('submit')。
- 禁用:
$('#submitBtn').attr('disabled', true).addClass('layui-btn-disabled') - 恢复:
$('#submitBtn').removeAttr('disabled').removeClass('layui-btn-disabled') - 若按钮带
lay-filter(如lay-filter="formSubmit"),推荐用属性选择器定位:$('button[lay-filter="formSubmit"]')
禁用时机必须在验证通过之后、AJAX 发出之前
提前禁用会跳过 form.verify(),导致必填项不校验就锁死 UI;延后禁用则可能被连点钻空子。正确顺序是:监听 form.on('submit') → 执行验证 → 验证通过后立刻禁用按钮 → 再发 AJAX。
特别注意异步验证场景(如用户名唯一性检查):不能等 done(true) 后再禁用,否则用户可能在等待响应时二次点击。应把禁用逻辑放在异步回调内部的最终成功分支里。
- 同步验证通过后禁用:
form.on('submit(demoForm)', function(data) { /* 校验 OK */ $('#submitBtn').attr('disabled', true).addClass('layui-btn-disabled'); $.ajax({ ... }); return false; }); - 异步验证中,禁用只能放在
done(true)的回调内,不能放外层 - 千万别在
$.ajax()的success里恢复按钮——失败时就卡死了,必须用always回调统一恢复
移动端 touchstart 阶段就要拦截,别等 click
安卓 WebView 或旧版 iOS 存在 300ms click 延迟,用户快速双击可能触发两次 click,即使你禁用了按钮,也可能因事件时序问题漏掉一次。
Layui 的 form.on('submit') 是基于 click 绑定的,无法覆盖这个底层延迟。最稳妥的方式是在 touchstart 阶段就禁用按钮,比 click 早得多。
- 给按钮加
touchstart监听:$('#submitBtn').on('touchstart', function() { $(this).attr('disabled', true).addClass('layui-btn-disabled'); }); - 避免同时监听
click和touchend,容易重复触发;统一用touchstart + click并在两者中都做禁用判断即可 - 如果用了
form.render()重绘表单(比如动态增删字段),禁用状态会丢失,需在 render 后重新设置
恢复按钮状态必须覆盖所有退出路径
按钮禁用后,只在 AJAX success 里恢复是危险的——网络超时、500 错误、用户手动刷新都会让按钮永远卡在禁用态。真正安全的做法是:无论成功失败,只要请求生命周期结束,就恢复。
最容易被忽略的是 loading 状态残留和表单重绘干扰。比如调用 form.render() 后按钮变回可用,但用户还没看到提示;或者 layer 弹窗关闭后忘记恢复按钮。
- 用布尔变量标记状态:
let isSubmitting = false;,禁用前设为true,always中设回false并恢复按钮 - 不要用
setTimeout延迟恢复,网络不可控,2 秒可能刚发请求就结束了 - 如果页面有多个提交入口(如 tab 切换后不同表单),确保每个入口都有独立的禁用/恢复逻辑,避免互相干扰











