disabled使控件彻底禁用、置灰、不可聚焦且值不提交;readonly仅禁止编辑,但允许聚焦、复制和提交值;fieldset disabled可批量禁用子控件,但仅对原生表单元素生效。

disabled 属性让输入框彻底失效
直接在 <input> 标签里写 disabled 就生效,它是个布尔属性,存在即禁用,不需要赋值:<input type="text" disabled>。浏览器会灰化该控件、阻止聚焦、拦截所有键盘和鼠标交互,最关键的是——表单提交时,这个字段的值根本不会出现在 FormData 或序列化结果里。
常见错误包括:
• 写成 disabled="false" 或 disabled="",照样禁用;
• 给 <label> 或 <div> 加 disabled,完全无效,只对原生表单控件(input、textarea、select、button、fieldset)起作用;
• 用 setAttribute('disabled', 'disabled') 启用/禁用,容易状态错乱,尤其在旧版 Safari 中后续再设 .disabled = true 可能失效。
正确做法是 JS 里统一用布尔赋值:
• 禁用:inputEl.disabled = true
• 启用:inputEl.disabled = false
• 判断:if (inputEl.disabled) { ... }
readonly 属性让输入框只读但保留提交
加 readonly 后用户不能编辑内容,但控件仍可聚焦、可选中、可复制,且它的值会随表单一起提交。典型场景是显示用户名、订单号这类“不可改但必须传给后端”的字段:<input type="text" value="admin" readonly>。
立即学习“前端免费学习笔记(深入)”;
注意:
• readonly 对 <radio>、<checkbox> 无效,它们本身不支持该属性;
• readonly="false" 没意义,只要属性存在就只读;
• 它不影响表单验证逻辑,比如带 required 的 readonly 输入框仍会触发校验失败;
• 如果你用 JS 动态设置,应写 inputEl.readOnly = true(注意大小写,是 readOnly,不是 readonly)。
fieldset disabled 批量禁用一组控件
把多个表单控件包进 <fieldset disabled>,比逐个加 disabled 更简洁、语义更准,且浏览器会递归禁用所有子控件(包括嵌套的 <fieldset>)。例如加载中防止重复提交:<fieldset disabled><input name="email"><button type="submit">提交</button></fieldset>。
要注意:
• <legend> 文本不受影响,仍可聚焦、可读取;如需屏蔽,得额外加 CSS 或 JS;
• 子控件显式写 disabled="false" 也无效,父级 fieldset 的禁用状态强制覆盖;
• IE11 等老浏览器对 fieldset:disabled 样式支持不一致,建议用 [disabled] 选择器做兼容性微调。
为什么禁用了却还收到空值或收不到值
这是最常踩的坑:后端收不到字段,往往不是 JS 没生效,而是前端选错了属性。
• 收不到值 → 用了 disabled,它天然排除在提交数据之外;
• 收到空值或默认值 → 可能 JS 修改了 value 但没同步更新 DOM 属性,或者 Vue/React 中仅操作了 DOM 的 .disabled 却没更新响应式状态,下次渲染被覆盖;
• 表单验证通过但值没传 → 检查是否混用了 readonly 和 disabled,或误在 <form> 标签上写了 disabled(HTML 规范不支持)。
服务端永远别信前端禁用了什么。绕过 disabled 只需删掉属性或发个 POST 请求就行,权限控制必须在后端校验。



















