按钮必须用 ,因其自带焦点管理、键盘支持和触控热区保障;role="button" 不可靠,禁用;需设 min-width/height: 44px、显式 type="button"、JS 控制 disabled 和 aria-busy,并精简 DOM 深度。

按钮必须用 <button></button>,不能用 <div> 或 <code><a></a> 模拟,否则在 iOS VoiceOver、Android TalkBack 下大概率被跳过,点不动也读不出。
为什么 <button type="button"></button> 是唯一安全起点
原生 <button></button> 自带焦点管理、:active 响应、键盘支持(Enter/Space)、最小触控热区保障;换成 <div class="btn"> 后,浏览器不认为它是可交互元素,<code>touchstart 要靠 JS 手动绑定,Safari 还可能跳过 :active 渲染。实测中,role="button" 在微信 X5 内核和部分低端安卓 WebView 中完全无效,且不自动获得 tabindex 或触发空格/回车。
-
type="button"必须显式声明——浏览器默认是submit,哪怕没套<form></form>也会误提交 - 禁用
role="button":它不响应keydown、不进焦点流、不触发:active,纯属埋坑 - 若需样式重置,用
button { all: unset; },再写自己的样式,别绕开语义
data-product-id 和触控尺寸必须同时达标
只加 data-product-id 不够,按钮本身 clientWidth × clientHeight 必须 ≥ 44×44px(WCAG 强制要求),否则 iPhone 上手指点不准,不是“体验差”,是合规风险。
-
data-product-id是 JS 识别商品的唯一可靠依据,别拼在href里或塞进class,那会让结构一改就失效 - 移动端必须设
min-width: 44px; min-height: 44px;,仅靠padding不可靠——inline元素的换行符会产生空白间隙,实际尺寸缩水 - 避免
display: inline-block+ 换行 HTML,改用display: block或flex并加align-items: center防止内容错位
点击后状态控制不能只靠 CSS 类
光加 .loading 类或改 opacity 不行,用户连点、网络慢、接口失败时,按钮仍可能重复提交。真实状态必须由 JS 控制 DOM 属性。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
立即学习“前端免费学习笔记(深入)”;
- 点击瞬间立刻执行
button.disabled = true和button.setAttribute('aria-busy', 'true') - 请求完成(无论成功失败)后,必须恢复
button.disabled = false和aria-busy="false",别只删 class - 失败后建议保留启用状态,并显示简短业务提示(如 “库存不足”),而不是 “请求失败”
- 禁用
pointer-events: none替代disabled——它会切断屏幕阅读器焦点和键盘支持
最易被忽略的是 DOM 深度:如果按钮嵌在 div > section > article > div > div > button 这种 6 层以上结构里,touchstart 到 handler 的延迟会翻倍(实测达 42ms),而人对“即时”的容忍阈值是 100ms。用 Chrome DevTools 右键按钮 → “Show DOM properties” 查 depth,超 6 就得砍掉无意义包裹层。


















