disabled是radio单选框禁用的唯一标准方案,它使控件不可交互、不提交值且视觉灰化;若需保留提交值,必须配合同名hidden输入框。

radio单选框加disabled属性最直接有效
HTML原生<input type="radio">没有readonly属性,强行写上不会生效。真正起作用的是disabled——它会让控件不可交互、不提交值、视觉灰化,是标准且兼容性最好的方案。
常见错误是误用readonly="true"或readonly,浏览器会忽略,用户依然能点击切换选项。
-
disabled后该radio的值**不会随表单提交**(这点和textarea或input[type=text]的readonly不同) - 如果只是想“禁止修改但保留提交值”,不能只靠HTML,需配合JS拦截+隐藏域补值
- 多个同名
radio中,只要有一个带disabled,它就无法被选中,但其他未禁用的仍可操作
需要保留提交值时,用disabled + <input type="hidden">组合
当服务端逻辑依赖某个radio的当前选中值,但前端又不允许用户更改时,单纯disabled会导致该值丢失。此时必须用隐藏域显式携带值。
示例:
立即学习“前端免费学习笔记(深入)”;
<input type="radio" name="plan" value="basic" disabled checked> <input type="radio" name="plan" value="pro" disabled> <input type="hidden" name="plan" value="basic">
注意:两个input的name必须完全一致,且隐藏域的value要与当前实际选中的radio值同步(服务端渲染时写死,或JS初始化时赋值)。
- 不要给隐藏域加
disabled,否则它也不提交 - 避免同名radio和hidden混用时出现多值提交(如用户能改其他radio),建议把原始radio全设为
disabled,只留一个hidden - 若用JS动态控制,记得在设置
disabled的同时更新hidden的value
用CSS模拟只读效果(不推荐,仅作了解)
有人尝试用pointer-events: none或opacity: 0.5加user-select: none假装只读,但这只是障眼法:键盘仍可通过Tab+Space切换,屏幕阅读器可能误读,且无法阻止JS触发click事件。
- 这种做法绕过了表单语义,对无障碍(a11y)不友好
- 移动端触控区域失效风险高
- 一旦JS稍有疏漏(比如没监听
change或click),状态就失控
React/Vue等框架里别忘了同步disabled状态
在受控组件中,仅靠JSX里写disabled={true}不够——如果状态变量没冻结,用户仍可能通过其他交互(比如按钮)意外修改checked或value。
例如React中:
const [selected, setSelected] = useState('basic');
// ❌ 错误:disabled是静态的,但setSelected仍可被调用
<input type="radio" name="plan" value="basic" disabled onChange={() => setSelected('basic')} />
// ✅ 正确:确保状态不可变,或禁用所有变更入口
<input type="radio" name="plan" value="basic" disabled checked={selected === 'basic'} />
关键点在于:禁用UI只是表层,必须同时切断状态更新路径,否则DOM和state会不一致。
真正难的不是加个disabled,而是确认“这个值是否该参与后续流程”——如果该值只是展示用途,disabled足够;如果它要进数据库或触发校验,就得额外处理提交逻辑和状态同步。



















