后端收不到字段八成是误用disabled而非readonly;disabled值不提交,readonly值照常提交;前者适用于功能锁死,后者适用于“只读但必传”场景。

后端收不到字段,八成是把 readonly 写成了 disabled。这不是样式问题,而是表单值是否进请求体的根本分水岭。
提交时字段值会不会发到后端?
这是唯一不可妥协的判断依据,其他所有差异都围绕它展开。
-
disabled的控件:浏览器在序列化表单(form.submit()、new FormData(form)、form.serialize())时直接过滤掉,哪怕 DOM 里value="123"明晃晃写着,后端也收不到name=123 -
readonly的控件:值照常提交,request.getParameter("id")或等价方式能正常取到,适合预填 ID、订单号、计算结果等“只读但必传”场景 - 典型翻车现场:
<input name="user_id" value="789" disabled>→ 上线后接口报“缺少必传参数”,查日志发现字段压根没进请求体
哪些元素支持 readonly?哪些必须用 disabled?
readonly 不是万能锁,硬加在不支持的标签上等于白写。
- 有效:
<input type="text">、<input type="password">、<input type="email">、<textarea></textarea> - 无效(浏览器直接忽略):
<select readonly></select>、<input type="checkbox" readonly>、<button readonly></button>、<input type="radio" readonly> -
disabled通吃全部:<select></select>、<button></button>、<fieldset></fieldset>都支持;<fieldset disabled></fieldset>还能递归禁用内部所有子控件 - 想实现“只读下拉框”?别写
select readonly,要么换成<input type="text" readonly>模拟,要么 JS 禁用每个<option disabled></option>
JS 动态控制 readonly 和 disabled 的坑点
脚本切换状态比静态写 HTML 更容易翻车,尤其跨浏览器兼容性。
- 设
disabled:直接写el.disabled = true或el.disabled = false,安全可靠 - 设
readonly:避免el.readOnly = false(某些旧版 Safari 不响应),稳妥做法是el.removeAttribute('readonly')启用,el.setAttribute('readonly', '')禁用 - 别同时写
readonly和disabled:disabled优先级更高,readonly形同虚设,还掩盖真实逻辑 -
disabled元素的value属性仍可读写,但修改后不会反映在 UI 上(UI 已冻结)
聚焦、复制、可访问性差异直接影响功能可用性
这不是体验优化项,而是刚需。
-
readonly允许:Tab 键切入、.focus()成功、双击选中、Ctrl+A全选、Ctrl+C复制,也支持focus事件监听 -
disabled彻底阻断:Tab 跳过、.focus()静默失败、无法选中或复制;CSS 的:focus或outline也无效 - 展示 API Key、手机号、调试 ID 等需要复制的字段,必须用
readonly;若误用disabled,用户点不动、选不了、也复制不了 -
input[readonly]默认不灰化,建议手动加background-color: #f5f5f5; cursor: not-allowed;做视觉提示;而input:disabled浏览器自带置灰,但泛写可能破坏移动端 WebView 匹配
最常被忽略的是:字段是否必须提交,决定了属性选择;而元素类型是否支持 readonly,决定了你能不能这么选。两者缺一不可。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











