点击按钮后应立即禁用并切换加载状态,而非等待请求返回;需在事件处理函数首行设置disabled和加载文案,用CSS控制SVG动画,失败后手动恢复状态并保持焦点。

点击按钮后立刻进入加载状态,不是等请求返回才动——这是防止重复提交的底线。
点击瞬间就禁用并替换内容
常见错误是把 disabled 和文字变更写在 fetch().then() 里,这时候网络请求早发出去了,用户仍能狂点。正确做法是在事件回调第一行就执行状态切换。
-
button.disabled = true必须放在事件 handler 开头,不可延迟 - 用
button.textContent = "加载中..."或插入内联<span class="spinner"></span>,避免依赖外部图标字体加载 - 若用 SVG 动画,直接写在 HTML 里(别用
background-image),方便 JS 控制显隐
用 CSS 实现不卡顿的旋转动画
纯 CSS 动画比 JS 驱动更稳,尤其在低端设备上。关键不是加个 animation: spin 1s infinite 就完事,得控制触发时机和层级。
- 定义
@keyframes spin,用transform: rotate(360deg),别用rotateZ(部分 Safari 不兼容) - 给 spinner 元素设
display: inline-block+vertical-align: middle,避免文字跳动 - 动画只在
.loading类存在时启用,JS 切换 class 即可,不操作 style 属性 - 避免对整个 button 做
opacity过渡——会模糊文字;改用visibility: hidden+height: 0配合overflow: hidden隐藏旧文字
失败后必须手动恢复按钮状态
网络请求失败不会自动撤回 disabled,也不还原文字。不处理这点,按钮就永远卡在 loading 状态。
立即学习“前端免费学习笔记(深入)”;
- 在
catch()或fetch().finally()里重置:button.disabled = false - 恢复原始文字不能靠
textContent硬编码,应提前存到data-original-text属性里 - 如果用了 spinner 元素,记得
button.querySelector(".spinner")?.remove(),否则多次点击会堆叠 - 服务端必须做幂等校验——前端防不住所有异常(比如页面刷新、代理重发)
最易被忽略的是:按钮恢复后,焦点状态可能丢失。如果用户用键盘操作,button.focus() 得手动补上,否则可访问性就断了。



















