单选按钮name属性必须一致才能实现互斥选择;需为每个radio设置value值并显式指定checked;用change事件委托监听更可靠;切换时应同步更新display和disabled状态,并清理校验信息。

单选按钮 name 必须一致才能互斥
浏览器只认同名的 <input type="radio"> 为一组,否则点击多个也能同时选中。这是动态切换的前提,很多人一开始没切成功,就是忘了统一 name 属性。
常见错误现象:console.log 显示多次触发、切换后内容不更新、两个选项看起来“都能选”。
-
name值建议用语义化字符串,比如"form-mode",别用"r1"这类无意义命名 - 每个
<input>必须带value,后续 JS 靠它判断当前选中态 - 初始状态建议显式设置一个
checked,避免首次加载时逻辑分支遗漏
用 addEventListener("change") 监听比 click 更可靠
change 事件在用户真正切换选项(且焦点离开或值确定)时才触发,而 click 在每次点击都发,容易重复执行或误判未生效的点击。尤其在移动端或快速连点时,click 可能导致表单内容闪动或错乱。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 绑定到父容器(如
<fieldset>或带id的<div>),用事件委托,避免为每个 radio 单独绑 - 在回调里用
event.target.value拿当前选中的值,别依赖querySelector再查一遍 - 确保监听器在 DOM 加载完成后注册,否则可能绑定失败 —— 放在
DOMContentLoaded里最稳
示例片段:
document.getElementById("mode-selector").addEventListener("change", (e) => {
if (e.target.type === "radio" && e.target.name === "form-mode") {
showSection(e.target.value); // 如:showSection("address") 或 "contact"
}
});
隐藏/显示对应表单区块,优先用 classList.toggle() 而非直接改 style.display
硬编码 style.display = "none" 会覆盖 CSS 中其他 display 设置(比如 flex/grid),还可能和媒体查询冲突。用 CSS 类控制更解耦、可维护性高,也方便加过渡动画。
使用场景:
- 为每类表单内容区块加唯一
data-section属性,如data-section="address" - 定义统一类名如
.section-hidden,CSS 里写.section-hidden { display: none; } - 切换时先给所有区块加
.section-hidden,再给目标区块移除
这样避免漏掉旧区块、也不用记哪些该显哪些该隐。
注意表单字段的 disabled 和验证状态同步
光隐藏 DOM 不够:被隐藏的 <input> 如果仍为 enabled,提交时还会参与序列化;若含必填(required),也可能触发浏览器原生校验提示。
所以切换时应一并处理:
- 对当前激活区块内的所有
input、select、textarea移除disabled - 对其他区块内的同类元素统一加上
disabled - 如果用了
Constraint Validation API(如checkValidity()),记得重置setCustomValidity(""),否则残留错误信息
这个细节常被跳过,结果是用户切到新模块后,点提交却弹出上一个模块的必填提示。
实际做下来,最难缠的不是切换逻辑本身,而是隐藏后字段状态没清干净 —— 尤其带自定义校验、第三方 UI 组件(如日期选择器)或动态生成的子表单时,disabled 和 display 得双管齐下。



















