
本文介绍如何使用原生 javascript 实现两级单选按钮联动:用户选择第一组(如游戏主机)后,第二组(对应游戏关卡)自动显示且仅包含相关选项,其余隐藏,无需刷新页面。
本文介绍如何使用原生 javascript 实现两级单选按钮联动:用户选择第一组(如游戏主机)后,第二组(对应游戏关卡)自动显示且仅包含相关选项,其余隐藏,无需刷新页面。
在构建交互式表单时,常需根据用户前序选择动态加载后续选项——例如先选游戏主机(SNES/N64/GBA),再从该平台专属关卡中选择。这种“依赖型单选表单”无需后端或框架,纯前端即可优雅实现。
核心思路是:监听第一组单选按钮(name="console")的 change 事件,根据选中的 value,动态显示对应预定义的第二组选项区块,同时隐藏其他无关区块。
以下为完整、可直接运行的实现方案:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>依赖型单选表单示例</title>
<style>
.course-group { display: none; margin-top: 1rem; }
.course-group.active { display: block; }
.course-group label { display: inline-block; margin-right: 1rem; }
</style>
</head>
<body>
<form id="mainForm">
<h3>请选择游戏主机:</h3>
<div class="original-game-selector">
<input id="SNES" type="radio" name="console" value="SNES" />
<label for="SNES">Super Nintendo (SNES)</label><br>
<input id="N64" type="radio" name="console" value="N64" />
<label for="N64">Nintendo 64 (N64)</label><br>
<input id="GBA" type="radio" name="console" value="GBA" />
<label for="GBA">Game Boy Advance (GBA)</label><br>
</div>
<!-- 预定义各主机对应的关卡组,初始全部隐藏 -->
<div id="coursesContainer" style="margin-top: 2rem;">
<!-- SNES 关卡组 -->
<div class="course-group" data-console="SNES">
<h4>SNES 可选关卡:</h4>
<input id="snes-bowser" type="radio" name="course" value="Bowser Castle 3" />
<label for="snes-bowser">Bowser Castle 3</label><br>
<input id="snes-donut" type="radio" name="course" value="Donut Plains 3" />
<label for="snes-donut">Donut Plains 3</label><br>
<input id="snes-yoshi" type="radio" name="course" value="Yoshi Valley" />
<label for="snes-yoshi">Yoshi Valley</label><br>
</div>
<!-- N64 关卡组 -->
<div class="course-group" data-console="N64">
<h4>N64 可选关卡:</h4>
<input id="n64-bowser" type="radio" name="course" value="Rainbow Road" />
<label for="n64-bowser">Rainbow Road</label><br>
<input id="n64-mario" type="radio" name="course" value="Mario Raceway" />
<label for="n64-mario">Mario Raceway</label><br>
</div>
<!-- GBA 关卡组 -->
<div class="course-group" data-console="GBA">
<h4>GBA 可选关卡:</h4>
<input id="gba-mushroom" type="radio" name="course" value="Mushroom Bridge" />
<label for="gba-mushroom">Mushroom Bridge</label><br>
<input id="gba-daisy" type="radio" name="course" value="Daisy Cruiser" />
<label for="gba-daisy">Daisy Cruiser</label><br>
</div>
</div>
</form>
<script>
// 获取所有主机单选按钮和容器
const consoleRadios = document.querySelectorAll('input[name="console"]');
const courseGroups = document.querySelectorAll('.course-group');
// 监听主机选择变化
consoleRadios.forEach(radio => {
radio.addEventListener('change', () => {
const selectedConsole = radio.value;
// 隐藏所有关卡组
courseGroups.forEach(group => {
group.classList.remove('active');
});
// 显示匹配的关卡组
const targetGroup = document.querySelector(`.course-group[data-console="${selectedConsole}"]`);
if (targetGroup) {
targetGroup.classList.add('active');
}
});
});
</script>
</body>
</html>✅ 关键说明与最佳实践:
- 使用
data-console属性精准关联主从逻辑,语义清晰、易于维护; - 所有子选项统一
name="course",确保单选互斥(同一时间仅能选一个关卡); - CSS 控制显隐(
display: none/block),比操作innerHTML更高效、安全,避免重复绑定事件或 XSS 风险; - 不依赖外部库,兼容所有现代浏览器;
- 若需提交表单,两个
<input>均位于同一<form></form>内,提交时将同时携带console和course的值。
? 进阶提示:如需支持“取消选择”或默认展开某组,可在 JS 中增加初始化逻辑(例如默认选中 SNES 并激活其关卡组)。此外,若数据量大,可将关卡数据转为 JSON 对象,用 JS 动态渲染,进一步提升可维护性。
通过此方案,你已掌握依赖型表单的核心模式——它同样适用于地区/城市联动、产品分类/型号选择等常见业务场景。

















