用 readonly 而非 disabled,除非后端明确不需要该字段值;readonly 保证提交,disabled 则完全不参与序列化;checkbox/radio 不支持 readonly,须用 disabled 配合 aria-disabled 和 fieldset。

用 readonly 还是 disabled?先看后端要不要这个值
如果表单提交后,后端收不到某个字段的值,八成是误用了 disabled。它会让字段完全不参与序列化——哪怕你在 JS 里改了 value,提交时照样消失。readonly 才是“只读但照常提交”的正解。只有当你明确不需要该字段值(比如占位提示、纯展示)时,才用 disabled。
Bootstrap 5 中 input[readonly] 没样式?必须手动加 CSS
Bootstrap 5 移除了对 [readonly] 的默认视觉反馈,输入框看起来和可编辑状态一模一样,用户点进去才发现输不了。不补样式 = 埋雷。
-
input[readonly]至少要设background-color: #e9ecef和cursor: not-allowed - 加
:focus样式提升可访问性:border-color: #86b7fe; box-shadow: 0 0 0 0.25rem rgba(134, 183, 254, 0.25) - 若用了
.form-control,优先写.form-control[readonly],避免污染全局input - 别用
pointer-events: none替代——它会阻止聚焦,键盘 Tab 进不去,残障用户无法操作
checkbox 和 radio 不支持 readonly,只能用 disabled + 补语义
<input type="checkbox"> 和 <input type="radio"> 原生不支持 readonly 属性,强行加无效。必须用 disabled,但光加属性远远不够:
-
label仍可点击,视觉无变化,用户无法感知禁用状态 - 给关联的
label加aria-disabled="true" - 同步设置
style="opacity: 0.6; cursor: not-allowed;"(仅作视觉提示,不可替代语义) - 更稳妥的做法:用
<fieldset disabled></fieldset>包裹整组控件,一次禁用全部且语义完整
JS 动态控制时,别混用 .prop() 和 .attr()
jQuery 里,$el.prop('disabled', true) 是标准写法;$el.attr('disabled', 'disabled') 在表单序列化或读屏软件中可能失效。原生 JS 更直接:
- 设只读:
el.readOnly = true(注意大小写是readOnly,不是readonly) - 移除只读:
el.removeAttribute('readonly')—— 别写el.readOnly = false,Safari 旧版有延迟 - 禁用按钮时,记得同步加
el.setAttribute('aria-disabled', 'true'),否则读屏软件不会播报状态变化
readonly 改成 disabled,或者漏掉样式覆盖——结果 QA 测出“字段明明填了却提交为空”,排查半天才发现是属性写错了。


















