按钮必须设 data-product-id 和 type="button",禁用状态需同步 disabled 属性与 aria-busy,移动端触控区不小于 44×44px 且避免 inline-block 间隙。

按钮必须带 data-product-id 才能被 JS 正确识别
没这个属性,点击后 JS 根本不知道加的是哪个商品。别用 id 或 class 混淆语义,也别把 ID 拼在 href 里(比如 href="add-to-cart?id=123"),那会让按钮变成跳转链接,破坏单页体验。
常见错误是只写 <button class="btn-add">加入购物车</button>,JS 只能靠 DOM 位置硬推 ID,页面结构一调就失效。
正确写法:<button type="button" data-product-id="1057">加入购物车</button>
如果商品有 SKU(如颜色/尺寸),建议同时加 data-sku-id,避免主 ID 无法区分库存单位;服务端渲染时,确保该值和后端 /cart/add 接口要求的 product_id 字段类型一致(字符串 or 数字)。
立即学习“前端免费学习笔记(深入)”;
type="button" 不是可选项,是防刷新的关键
很多页面把按钮放在 <form></form> 里却不设 type,结果点击直接触发表单 submit,页面刷新或跳转,购物车请求根本没发出去。
浏览器对 <button></button> 的默认行为就是 submit,不是“无动作”。哪怕没套 form,也建议显式声明 type="button"。
错误写法:<button>加入购物车</button>(在 form 内 = 提交)
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
安全写法:<button type="button" data-product-id="1057">加入购物车</button>
若真要用表单(比如带数量输入框),则用 <button type="submit"></button> 配合 event.preventDefault() 和 AJAX,但没必要增加复杂度。
移动端触控区必须 ≥ 44×44px,且不能依赖 padding 补救
小按钮在 iPhone 上难点击,不只是体验差,更是 WCAG 合规风险。别信“加个 padding 就行”——inline-block 元素间的换行符会产生空白间隙,导致实际宽度缩水。
推荐做法:
- 用
display: flex或block布局,避免inline-block间隙问题 - 设置
min-width: 44px; min-height: 44px;,再配合padding提升视觉大小 - 用
touch-action: manipulation加速移动端点击响应
别为了“好看”牺牲可点性,按钮再精致,点不中等于不存在。
禁用状态和加载反馈不能只靠 CSS 类名切换
用户连点、网络慢、接口重复调用——这些都得靠 JS 控制真实 DOM 状态。光加 .loading 类或改背景色,漏掉 disabled 属性,按钮仍可点击。
真正要做的:
- 点击后立刻执行
button.disabled = true - 同步设置
button.setAttribute('aria-busy', 'true'),供屏幕阅读器识别 - 请求完成(无论成功失败)后,优先用
button.disabled = false恢复,而不是删 class - 失败后建议保留启用状态,并显示简短业务提示(如 “库存不足”),而非笼统的 “请求失败”
DOM 状态比样式更可靠,而 aria-busy 是容易被忽略但影响无障碍体验的关键点。


















