应优先用 readonly 而非 disabled 以确保字段值提交;disabled 使字段不可交互且不参与提交,readonly 仅禁编辑但值照常提交;Bootstrap 5 需手动添加 readonly 样式并注意可访问性。

别直接加 disabled,除非你真不想要那个字段的值——后端收不到,校验通了也白搭。
readonly 和 disabled 的提交行为差异
这是最常踩的坑:表单提交后,后端发现某个字段为空,查前端代码却发现“明明填了”。原因往往是误用了 disabled 而非 readonly。
-
disabled:元素不可交互、不可聚焦、不可复制,且不会出现在表单提交数据中(无论你在 JS 里改了多少次value) -
readonly:可聚焦、可选中、可复制,值照常随表单提交,仅禁止用户手动编辑 - 两者同时存在时,
disabled优先级更高,readonly被忽略 -
<select></select>和<textarea></textarea>支持readonly;<input type="checkbox">和<input type="radio">不支持,只能用disabled或 JS 拦截
Bootstrap 5 中 readonly 输入框没样式?必须手动补
Bootstrap 5 移除了对 [readonly] 的默认视觉反馈——输入框看起来和可编辑状态一模一样,用户点进去才发现输不了,体验差且易被误操作。
- 必须手动加 CSS,例如:
input[readonly] { background-color: #e9ecef; cursor: not-allowed; } - 别只靠
pointer-events: none,它会阻止聚焦,破坏可访问性 - 如果用了
.form-control,建议用.form-control[readonly]选择器覆盖,避免影响全局input - 旧版 IE 对
readonly的focus行为不一致,如需兼容,可用disabled+ 隐藏域<input type="hidden">补值
JS 动态控制时,别混用 .prop() 和 .attr()
jQuery 里 .prop('disabled', true) 是正确做法;.attr('disabled', 'disabled') 在某些场景下语义不完整,尤其在表单序列化或屏幕阅读器中可能失效。
- 原生 JS 推荐直接操作属性:
el.disabled = true或el.readOnly = true - 移除
readonly时,稳妥写法是el.removeAttribute('readonly'),而非el.readOnly = false(Safari 旧版本有延迟) - 动态禁用按钮时,记得同步设置
el.setAttribute('aria-disabled', 'true'),否则读屏软件可能无法播报状态变化 - 对
<fieldset></fieldset>设置disabled,能批量禁用内部所有控件,比逐个操作更可靠
Checkbox / Radio 禁用时,label 视觉与语义要同步
<input type="checkbox"> 不支持 readonly,只能用 disabled。但光加属性还不够——label 仍可点击,视觉上也没变化,残障用户和普通用户都难判断状态。
- 给
<label></label>加aria-disabled="true",并手动设style="cursor: not-allowed; opacity: 0.6;" - 确保
<input>的disabled属性真实存在,不能只靠 class 模拟 - 如果 label 里有图标或文字强调,也要同步灰阶处理,否则视觉割裂
- 别忘了测试键盘 Tab 切换:禁用后应跳过该组控件,而不是卡在 label 上
真正麻烦的不是写几行 CSS,而是团队里有人随手把 readonly 写成 disabled,或者漏掉 [readonly] 样式覆盖——结果 QA 测出来“这个字段明明只读,为什么用户还在狂点?”











