readonly仅对text类input和textarea生效,不影响表单提交;disabled则阻止提交且禁用交互;后端必须校验readonly字段防篡改。

readonly 属性不是“禁止修改”的万能锁,它是前端体验层的只读提示,值仍会随表单提交——这点必须先确认清楚,否则后端收不到数据或误判业务状态。
哪些元素能用 readonly 且真正生效
只对两类元素起作用:<input>(限 text、password、email、tel、url、search、date 等文本类)和 <textarea>。其他如 <select>、<button>、<input type="checkbox"> 加了 readonly 浏览器直接忽略,不会报错也不会生效。
常见踩坑点:
- 给
<input type="hidden">加readonly—— 无效,且没意义;hidden 本就不该被编辑 - 在 Vue 或 React 中写成
:readonly="true"却忘了绑定的是布尔值,实际渲染成readonly="true"(XHTML 风格),现代 HTML5 推荐直接用readonly属性名存在即为真 - 用
setAttribute("readonly", "")后又用removeAttribute("readonly")恢复,但旧版 Safari 对readOnly = false支持不稳,建议统一用removeAttribute
readonly 和 disabled 的行为差异直接影响表单逻辑
关键区别不在“能不能改”,而在“是否参与交互流程”:
-
readonly元素仍可获得焦点、可选中、可复制、可 Tab 切入,且name和value一定随表单提交 -
disabled元素完全失焦、不可复制、灰色置灰、不触发任何事件,且该字段 不会出现在提交数据中 - 如果后端依赖该字段做校验(比如用户 ID、订单号),却用了
disabled,就会收不到值,导致 400 或逻辑中断 - 若需视觉禁用 + 保留提交能力,
readonly是唯一合理选择;若只是临时屏蔽操作(如提交中按钮),才用disabled
动态控制 readonly 的 JS 写法要避开兼容性陷阱
用原生 JS 控制时,别直接赋值 element.readOnly = false,尤其在 Safari 15 及更早版本中可能失效:
- 设为只读:
el.setAttribute("readonly", "readonly")或el.readOnly = true(推荐前者,语义明确) - 解除只读:
el.removeAttribute("readonly")(比el.readOnly = false更可靠) - jQuery 用户注意:
.prop("readonly", true)是正确用法,.attr("readonly", true)在某些版本中可能不触发 DOM 属性同步 - Vue 场景下,绑定
:readonly="isLocked"完全可行,但需确保isLocked是响应式数据,且初始值准确(比如从 API 拿到“已核对”状态后才设为true)
后端必须校验 readonly 字段是否被篡改
用户打开开发者工具删掉 readonly 属性、改完值再提交,浏览器照发——这是设计使然,不是漏洞。
所以后端不能信任该字段“未被改过”,而应:
- 比对数据库原始值(例如:提交的
user_code是否等于当前用户记录中的user_code) - 结合时间戳或操作签名判断合法性(如该字段只允许在创建时设定,后续所有更新请求都应拒绝变更)
- 避免把
readonly当作权限控制手段,它不提供任何安全边界
最易被忽略的一点:前端加了 readonly,后端却没做对应字段的幂等校验或来源比对,等于白加。

















