后端收不到字段?八成是把readonly写成了disabled;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允许:Tab 键切入、.focus()成功、双击选中、Ctrl+A全选、Ctrl+C复制,也支持focus事件监听 -
disabled彻底阻断:Tab 跳过、.focus()静默失败、无法选中或复制;CSS 的:focus或outline也无效 - 展示 API Key、手机号、调试 ID 等需要复制的字段,必须用
readonly;若误用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>—— 浏览器直接忽略该属性 -
disabled通吃全部:<select></select>、<button></button>、<fieldset></fieldset>都支持;<fieldset disabled></fieldset>还能递归禁用内部所有子控件 - 想实现“只读下拉框”?别写
select readonly,要么换成<input type="text" readonly>模拟,要么 JS 禁用每个<option disabled></option>,或者改用纯文本展示
JS 动态控制时容易出错的点
脚本切换状态比静态写 HTML 更容易翻车,尤其跨浏览器兼容性。
- 设
disabled:直接写el.disabled = true或el.disabled = false,安全可靠 - 设
readonly:避免el.readOnly = false(某些旧版 Safari 不响应),稳妥做法是el.removeAttribute('readonly')启用,el.setAttribute('readonly', '')禁用 - 别同时写
readonly和disabled:disabled优先级更高,readonly形同虚设,还掩盖真实逻辑 - React/Vue 中绑定
readOnly属性时,注意 UI 库(如 Ant Design)可能没强调它不影响提交,测试阶段才发现后端少字段
真正容易被忽略的是:readonly 默认不灰化,外观和普通输入框一模一样;若不手动加 input[readonly] { background: #eee; cursor: not-allowed; },用户根本看不出它是只读的。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











