后端收不到字段大概率是前端误用了disabled而非readonly;disabled元素的值会被浏览器过滤,readonly则正常提交;readonly仅对文本类控件生效,select等需特殊处理。

后端收不到字段?先查是不是用了disabled而不是readonly
表单提交后服务端拿不到某个字段,八成是前端误用了disabled。浏览器在构造FormData、执行form.serialize()或原生submit时,会直接过滤掉所有disabled元素的name和value;而readonly元素的值照常出现在请求体中。request.getParameter("id")能取到,说明用了readonly;取不到,大概率是disabled写错了。
readonly只对<input type="text">、<textarea>等少数元素生效
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>;checkbox/radio需保留选中态但禁交互,得用disabled + 同名<input type="hidden">补值。
JS 动态控制readonly和disabled的坑
脚本切换状态比静态写 HTML 更容易翻车:
立即学习“前端免费学习笔记(深入)”;
- 设
disabled:必须用el.disabled = true或el.disabled = false,别用setAttribute('disabled', '')——旧版 IE 下可能不重绘,且移除时还得removeAttribute('disabled') - 设
readonly:老版 Safari 对el.readOnly = false响应慢;稳妥做法是禁用时el.setAttribute('readonly', ''),启用时el.removeAttribute('readonly') - 别同时写
readonly和disabled:后者优先级更高,readonly被覆盖,逻辑反而难排查 - 判断状态别用
getAttribute("readonly")(返回null或字符串),应始终用el.readOnly(注意大小写)布尔值
视觉和可访问性差异不能靠默认样式糊弄
disabled元素自带灰阶、cursor: not-allowed、自动加aria-disabled="true",屏幕阅读器会播报“已禁用”;readonly外观和普通输入框一模一样,用户可能误点去改——你得自己加 CSS,比如background: #eee; color: #666;,否则它看起来就像个能编辑的框。
更关键的是,readonly仍可聚焦、可选中、可复制,这对展示订单号、API Key、计算结果等场景是刚需;而disabled按钮连onclick都不会触发,哪怕绑了事件也白搭。
真正容易被忽略的,是fieldset上设disabled能批量禁用内部所有子控件,包括<select>和<button>,且语义清晰、兼容性好——比逐个加disabled靠谱得多。



















