应使用 <button> 而非 <div onclick> 实现按钮功能,因其原生支持语义、键盘导航(Tab/Enter/Space)、表单集成、禁用态及无障碍访问,而 <div> 需手动补全整套逻辑且易出错。

div 没有 button 的语义,屏幕阅读器读不出来“按钮”
用户用 VoiceOver 或 NVDA 听网页时,<div onclick> 被识别为普通文本,比如只读“关闭”,而不是“关闭按钮”。而 <button> 自带 role="button",无需额外声明,辅助技术直接宣布其可操作性。这不是“加个 ARIA 标签就能修好”的问题——它本质是缺失语义层级,连 DOM 树里都不存在交互节点类型。
键盘用户按 Tab 会跳过 div,Enter/Space 也不触发点击
原生 <button> 默认有 tabindex="0",自动进入焦点流;同时监听 keydown 事件,在 event.key === 'Enter' 或 event.key === ' '(注意:是空格键,且必须等按键释放才触发)时派发 click。而 <div> 不做任何事:
• 手动加 tabindex="0" 只解决聚焦,不解决触发
• 只监听 keydown 不够,漏掉 keyup 判断会导致 Space 键行为错乱
• 没处理 preventDefault() 时,空格键还会滚动页面
表单里没写 type 的 button 会默认 submit,div 却完全绕过表单逻辑
在 <form> 内部:
• <button> 默认是 type="submit",点一下就触发表单提交(哪怕没 JS)
• <button type="button"> 显式声明后才不干扰表单
• <div> 完全不参与表单生命周期:不会被 form.elements 收集,required 验证无视它,form.reset() 对它无效
• 更隐蔽的坑:如果误把 <div> 放进 <form> 还绑了 onclick,用户按 Enter 提交表单时,可能意外触发两次逻辑(一次原生 submit,一次 JS click)
视觉反馈和禁用态必须手动补全,且极易遗漏
<button disabled> 自动灰掉、阻止所有事件、继承 cursor: not-allowed;而 <div>:
• 必须同时加 aria-disabled="true" 和自定义 CSS(比如 opacity: 0.5)
• 忘写 cursor: pointer?鼠标悬停时没有手型,用户不确定能否点
• 用了 all: unset 却漏掉 user-select: none?双击会选中文字
• 禁用状态下仍响应 onclick?得靠 JS 手动判断 aria-disabled 值并 return
立即学习“前端免费学习笔记(深入)”;
真正麻烦的不是“能不能实现”,而是每次都要重复补全这一整套链路——焦点管理、键盘事件周期、语义角色、表单集成、视觉状态同步。浏览器早把这套逻辑固化在<button> 里了,没必要自己造轮子。



















