禁用按钮必须用prop('disabled', true),而非attr;需同步加类、改文字、插加载图标;恢复逻辑须统一放ajax的complete钩子中并缓存按钮引用;校验失败时立即恢复;移动端应在touchstart拦截;避免重复引入layui.js。

form.on 里禁用按钮必须用 prop('disabled', true),不是 attr
禁用失败的最常见原因就是用了 attr('disabled', 'disabled')。它只改 HTML 属性,不触发 DOM 的实际禁用语义,尤其在 Chrome 和新版 Edge 下完全无效。正确做法是直接操作属性状态:$(this).prop('disabled', true) —— 这才是真正让浏览器阻止后续点击的底层动作。
同时要同步做三件事,缺一不可:
- 加
layui-btn-disabled类,提供视觉灰化效果 - 替换文字,比如改成
提交中…或插入<i class="layui-icon layui-icon-loading"></i> - 确保这行代码写在
form.on('submit(...)')回调函数的最开头,不能被return false或验证逻辑挡住
成功、失败、超时都得在 complete 里恢复按钮
只在 success 里恢复按钮是典型错误。后端返回 500、网络中断、请求超时,甚至用户切走再切回来,都会导致按钮永远卡在 disabled 状态,整个表单失活。
必须把恢复逻辑统一收口到 $.ajax() 的 complete 钩子中:
$.ajax({
url: '/api/submit',
data: data.field,
complete: function() {
$(this).prop('disabled', false)
.text('提交')
.removeClass('layui-btn-disabled');
}
});
注意:这里 this 指向的是被点击的按钮(需提前缓存或用闭包传入),不能直接在 complete 里用 $(this)——因为此时 this 是 XHR 对象。稳妥写法是先存变量:var $btn = $(this);,然后在 complete 里用 $btn.prop(...)。
表单校验失败时也要立刻恢复按钮
很多人只在 AJAX 完成后恢复,却忘了 form.verify() 同步校验失败时按钮还处于 disabled 状态。用户根本没法改完再点——等于把表单锁死了。
所以只要校验没通过,就得立即恢复:
- 如果用了自定义
form.verify,在return false前加恢复逻辑 - 如果用了异步验证(如用户名查重),必须等
done(true/false)回调执行完、确认校验结果后再决定是否禁用 - 别在禁用按钮前调用
return false,否则恢复代码压根不执行
移动端要防 touchstart 阶段的连击
安卓 WebView 或旧版 iOS 存在 300ms click 延迟,用户快速双击可能触发两次 click,而 form.on 绑定的是 click 事件,来不及响应第一次禁用。
解法是在 touchstart 阶段就提前拦截:
$('button[lay-submit]').on('touchstart', function() {
var $btn = $(this);
if (!$btn.prop('disabled')) {
$btn.prop('disabled', true)
.text('提交中…')
.addClass('layui-btn-disabled');
}
});
注意:这个监听要放在 form.on 外部,且仅对移动端生效(可加 UA 判断),否则 PC 端会干扰正常 focus 行为。
重复引入 layui.js 或混用 layui.js 与 layui.all.js 会导致 form.on 绑定多次,一个点击触发多轮提交——这是最隐蔽的“按钮点了没反应但后端收到两份数据”的根源,务必检查 script 标签去重。


















