要让 <input> 真正只读且不聚焦,需同时设置 readonly、tabindex="-1" 和 onfocus="this.blur()";readonly 字段提交时仍传值,而 disabled 不传。

如何让 <input> 真正只读不聚焦
只加 readonly 属性并不等于“不可编辑”——它仍可被聚焦、选中、复制,甚至被键盘导航到。如果你要的是视觉上禁用 + 完全跳过交互,readonly 不够,得配合 tabindex="-1" 和 aria-readonly="true"(尤其对屏幕阅读器友好)。
-
readonly:允许聚焦,但阻止输入;适合需要复制值的场景(如订单号预填) -
disabled:彻底禁用,不提交、不聚焦、样式变灰;但表单提交时该字段会被忽略 - 真正“只读且不参与交互”:用
readonly+tabindex="-1"+onfocus="this.blur()"(防键盘意外聚焦)
readonly 输入框在表单提交时会不会传值?
会。这是它和 disabled 最关键的区别:readonly 字段的 value 会随表单一起提交,后端能正常收到;disabled 字段则完全不出现在 FormData 或 request.body 中。
- 常见踩坑:用
disabled显示用户 ID,结果后端收不到,报Missing required field - 修复方式:改用
readonly,再加 CSSpointer-events: none;防点击(注意这不影响键盘操作) - React 中注意:别用
value+onChange同时控制,否则readonly失效;直接设value和readOnly即可
CSS 控制 readonly 输入框的视觉状态
浏览器默认不会给 readonly 元素加特殊样式,所以它看起来和可编辑框一模一样,容易误导用户。必须手动用伪类 :read-only 区分。
- 推荐写法:
input:read-only { background-color: #f5f5f5; cursor: default; } - 别依赖
[readonly]属性选择器——它匹配所有带该属性的元素,包括disabled,而:read-only只匹配真正只读(非禁用)的状态 - 移动端 Safari 对
:read-only支持良好,但旧版 Android Webview 可能不支持,可降级用[readonly]:not([disabled])
React/Vue 中绑定 readonly 的典型错误
框架里最常犯的错是把 readonly 当成响应式 prop 来“动态切换”,却忘了它本质是 HTML 布尔属性:只要存在就生效,删掉才失效。直接用布尔值控制会出问题。
立即学习“前端免费学习笔记(深入)”;
- React 错误写法:
<input readOnly={isEditable ? false : true} />→ 实际渲染为readOnly="false",浏览器仍当它是只读(因为属性存在) - 正确写法:
{isEditable ? <input /> : <input readOnly />}或<input readOnly={isEditable === false} />(注意不是字符串) - Vue 中同理:
:readonly="!isEditable"是对的,readonly="{{ !isEditable }}"(老写法)可能输出字符串导致异常
readonly,Tab 键仍能停在上面,对键盘用户不友好。这点在无障碍验收时经常被卡住。











