后端收不到字段通常因误用disabled而非readonly;disabled元素值不参与表单序列化,readonly则正常提交。只读且需复制时用readonly,禁用且不提交时用disabled。

后端收不到字段?八成是把 disabled 写成了 readonly —— 这不是样式问题,是值进不进请求体的根本分水岭。
表单提交时字段值会不会发到后端?这是唯一判断依据
浏览器构造 FormData、执行 form.submit() 或 jQuery 的 .serialize() 时,对两个属性的处理逻辑完全不同:
-
disabled元素:被完全过滤,name和value都不会出现在请求数据中,哪怕你用 JS 改了value也无效 -
readonly元素:值正常参与序列化,后端可通过request.getParameter("id")或等价方式取到
典型翻车现场:<input name="user_id" value="789" disabled> → 后端日志查不到 user_id,接口报“缺少必传参数”。
所以直接问自己:这个字段用户要看到、要复制、后端还必须收到?→ 用 readonly;只是临时锁死、且不希望它进请求?→ 用 disabled。
readonly 哪些元素支持?别白加
readonly 不是万能锁,它只对特定元素生效,硬加在不支持的标签上等于没写:
- 有效:
<input type="text">、<input type="password">、<input type="email">、<textarea></textarea> - 无效(浏览器直接忽略):
<select readonly></select>、<input type="checkbox" readonly>、<button readonly></button>
替代方案:
-
<select></select>只读需求:改用<input type="text" readonly>模拟,或 JS 控制每个<option disabled></option> -
<input type="checkbox">需视觉只读但保留状态:用disabled+ 同名<input type="hidden">补值
JS 动态控制 readonly 和 disabled 的坑
静态写 HTML 很直观,但 JS 切换状态容易出兼容性问题:
- 设
disabled:安全写法是el.disabled = true或el.disabled = false;避免用setAttribute('disabled', ''),移除时还得额外removeAttribute('disabled') - 设
readonly:别用el.readOnly = false(旧版 Safari 不响应);稳妥做法是禁用时el.setAttribute('readonly', ''),启用时el.removeAttribute('readonly') - 千万别同时写
readonly和disabled——disabled优先级更高,readonly形同虚设,还掩盖真实逻辑意图 - 判断状态别用
getAttribute("readonly")(返回null或字符串),应始终用el.readOnly(注意大小写)布尔值
聚焦、复制、可访问性差异不是体验优化,而是功能刚需
readonly 允许:Tab 切入、鼠标点击聚焦、.focus()、双击选中、Ctrl+A、Ctrl+C;也支持监听 focus 事件
disabled 彻底阻断:Tab 跳过、.focus() 静默失败、无法选中或复制;:focus 伪类不触发,outline 也不显示
展示 API Key、调试 ID、金额等需复制的字段,必须用 readonly;用 disabled 用户点不动、选不了、也复制不了。
另外:readonly 默认无视觉变化(看起来完全可编辑),容易造成用户困惑;实际项目中几乎总要配 CSS:input[readonly] { background-color: #f5f5f5; cursor: default; }
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











