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

后端收不到字段,八成是把 readonly 写成了 disabled;两者在表单提交时行为截然不同——disabled 的值根本不会进请求体,readonly 的值照常提交。
表单提交时字段是否进请求体?这是唯一判断依据
浏览器序列化表单(form.submit()、new FormData(form)、form.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> - 无效(浏览器直接忽略):
<select readonly>、<input type="checkbox" readonly>、<button readonly>
替代方案:
-
<select>只读需求:改用<input type="text" readonly>模拟,或 JS 禁用所有<option disabled> -
<input type="checkbox">需视觉只读但保留值:用disabled+ 同名<input type="hidden">补值
JavaScript 动态切换时容易出错的点
脚本控制比静态写 HTML 更容易翻车,尤其跨浏览器兼容性:
- 设
disabled:安全写法是el.disabled = true或el.disabled = false;避免用setAttribute('disabled', ''),移除时需额外removeAttribute - 设
readonly:老版 Safari 对el.readOnly = false响应迟钝;稳妥做法是禁用时el.setAttribute('readonly', ''),启用时el.removeAttribute('readonly') - 别同时写
readonly和disabled:后者优先级更高,前者被覆盖,逻辑反而更难排查 - 用
getAttribute("readonly")判断状态不可靠(返回null或字符串),应始终用el.readOnly(注意大小写)布尔属性
视觉和可访问性差异不能忽视
默认样式上,disabled 元素会变灰、cursor: not-allowed;而 readonly **外观和普通输入框一模一样**,用户可能误以为能编辑。
所以实际项目中,readonly 几乎总要配 CSS:
input[readonly] {
background: #f5f5f5;
color: #666;
cursor: default;
}
另外,disabled 元素会被屏幕阅读器跳过,readonly 仍可聚焦、可播报、可复制——这对视障用户是关键差异。切状态时若不手动管理焦点(比如从编辑态切到 readonly 后未 blur()),键盘用户可能卡在不可编辑却可聚焦的字段上。



















