应使用 readonly 而非 disabled,因 readonly 允许字段聚焦、选中、复制且值可提交,disabled 则完全禁用参与表单序列化;bootstrap 5 需手动添加 css 提供视觉反馈,js 控制须用 el.readonly = true 或 .prop('readonly', true)。

直接用 readonly 属性,别碰 disabled —— 否则后端收不到值,这是最常翻车的地方。
为什么 readonly 比 disabled 更适合“只读但要提交”的场景
表单里有些字段是预填的、用户只能核对不能改(比如手机号、订单号),这类字段必须保留提交能力。disabled 会让浏览器彻底忽略该字段:不参与序列化、不随 form.submit() 发送、JS 改了 value 也没用;而 readonly 只禁编辑,其他一切照常。
-
readonly:可聚焦、可选中、可复制、值照常提交 -
disabled:不可聚焦、不可选中、不可复制、值被表单自动剔除 - 两者同时存在时,
disabled生效,readonly被无视 -
<select></select>和<textarea></textarea>支持readonly;<input type="checkbox">和<input type="radio">不支持,只能用disabled或 JS 拦截
Bootstrap 5 中 readonly 输入框没样式?必须手动补
Bootstrap 5 移除了对 input[readonly] 的默认视觉反馈,输入框看起来和可编辑状态一模一样,用户点进去才发现输不了——这会引发误操作和 QA 投诉。
- 加 CSS 覆盖即可,推荐用
.form-control[readonly]选择器,避免影响全局input - 示例样式:
code.form-control[readonly] { background-color: #e9ecef; cursor: not-allowed; } - 别用
pointer-events: none:它阻止聚焦,破坏键盘 Tab 导航和屏幕阅读器体验,iOS Safari 还有兼容问题 - 别用
contenteditable="false":对input无效,浏览器直接忽略
动态控制只读状态时,JS 写法要小心
用原生 JS 或 jQuery 控制时,属性操作必须语义准确,否则表单序列化、可访问性都会出问题。
- 原生 JS 设置:
el.readOnly = true(注意大小写是readOnly,不是readonly) - 移除只读:
el.removeAttribute('readonly'),别写el.readOnly = false(Safari 旧版有延迟) - jQuery 推荐用
.prop('readOnly', true),别用.attr('readonly', 'readonly')—— 后者在某些场景下无法被表单序列化识别 - Vue 中绑定
:readonly.prop,React 中直接readOnly={isReadonly}即可
最容易被忽略的是:只加 readonly 属性却不补样式,尤其在 Bootstrap 5 项目里。用户看到输入框长得和能编辑的一样,就会反复点击、尝试输入,然后抱怨“这个字段怎么不响应”。视觉反馈不是锦上添花,而是可用性的底线。











