禁用按钮应使用`button.disabled=true`属性而非仅添加CSS类,因属性可阻止点击、提交及焦点;旋转加载图标需用Bootstrap5的`spinner-border`动态插入DOM;状态恢复代码统一放在`finally`块中,保证异常时也能执行;移动端另需设置`aria-disabled`、`tabIndex`和`pointer-events
button.disabled = true,而非添加 disabled 类Bootstrap 5 不再响应 class="disabled" 来真正禁用按钮——该方式仅修改样式,不会拦截点击、阻止键盘(空格/回车)输入,也无法影响表单序列化。按钮视觉上可能变灰,但用户依然可以连续点击、通过 Tab 键聚焦后按回车提交表单。唯一的可靠方式是直接操作原生属性:button.disabled = true 或 button.setAttribute('disabled', '')。浏览器会自动应用 button:disabled 样式规则(包括 opacity: .65 和 pointer-events: none),从而在语义、视觉和行为上保持一致。
spinner-border 插入 DOM,而非伪元素或纯 CSS 动画使用伪元素旋转(如 ::after { animation: spin })容易导致文字偏移或按钮宽度跳变,尤其在小尺寸按钮中;纯 CSS 动画也难以稳定控制尺寸与居中对齐。Bootstrap 5 自带的 spinner-border 更加可靠,操作步骤如下:
长期稳定更新的攒劲资源: >>>点此立即查看<<<
button.innerHTML = ''const spinner = document.createElement('span');,设置 className = 'spinner-border spinner-border-sm',添加 role="status" 和 aria-hidden="true"button.insertAdjacentText('beforeend', '提交中')...)finally 块中,并成套还原仅在 .then() 中恢复状态时,若接口返回 400/500 错误会卡死;仅在 .catch() 中恢复,则成功后可能遗漏还原。正确做法是在请求链的末尾统一清理:
.finally(() => { button.removeAttribute('disabled'); button.textContent = originalText; })button.disabled = false——某些旧浏览器可能不会触发样式重绘AbortController,finally 中也应调用 abortController.abort()aria-disabled 和 tabIndex:禁用时设置 aria-disabled="true" 与 tabIndex = -1,还原时移除属性并设置 tabIndex = 0部分安卓 WebView 和老版 Safari 对 disabled 属性中的 pointer-events 拦截不够彻底,手指轻点可能穿透到背后元素;NVDA 配合 Firefox 等读屏器有时不会播报纯 disabled 状态。因此需要补充以下处理:
button.setAttribute('aria-disabled', 'true')、button.tabIndex = -1、button.style.pointerEvents = 'none'button.removeAttribute('aria-disabled')、button.tabIndex = 0、button.style.pointerEvents = ''button.style.position = 'relative' 防止层叠错乱最容易忽略的是:原始文案必须提前缓存(例如存储到 dataset.originalText 中),否则还原时图标或空格会被清空;此外,按钮类型应设为 type="button",否则在表单内会默认触发表单提交,导致逻辑执行两次。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述