
本文介绍如何通过原生 javascript 实现两级联动下拉菜单,即根据第一个下拉框(如国家)的选择,动态显示第二个下拉框(如城市)中对应的可选值,采用 fieldset 分组 + 启用/禁用方案,兼顾语义性、可访问性与表单提交安全性。
本文介绍如何通过原生 javascript 实现两级联动下拉菜单,即根据第一个下拉框(如国家)的选择,动态显示第二个下拉框(如城市)中对应的可选值,采用 fieldset 分组 + 启用/禁用方案,兼顾语义性、可访问性与表单提交安全性。
在构建多级依赖型表单(如“国家 → 城市”)时,推荐避免频繁操作 DOM(如清空并重写 <option></option>),而应采用结构化预置 + 状态控制的方式。本方案使用 <fieldset></fieldset> 对每组城市选择器进行逻辑分组,并通过 disabled 属性控制其可见性与表单参与性——这不仅语义清晰、无障碍友好,还能确保被禁用的字段不会随表单提交,无需额外过滤。
✅ 核心实现逻辑
- 每个国家选项(如
"Ug"、"Ke")对应一个独立的<fieldset name="Ug"></fieldset>; - 所有 fieldset 初始设为
disabled,CSS 配合fieldset:disabled { display: none; }隐藏; - 监听
#countryselect的change事件,获取选中值(如"Ug"); - 全局禁用所有 fieldset,再启用与选中值同名的 fieldset(
form["Ug"].disabled = false)。
? 完整示例代码
<style>
fieldset {
border: none;
margin-top: 8px;
}
fieldset:disabled {
display: none;
}
.form-control-selector {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
}
</style>
<form name="form01">
<label for="countryselect">选择国家:</label>
<select class="form-control-selector" name="countryselect" required>
<option value="" selected>- 选择国家</option>
<option value="Ug">乌干达 (Ug)</option>
<option value="Ke">肯尼亚 (Ke)</option>
<option value="Rw">卢旺达 (Rw)</option>
<option value="Tz">坦桑尼亚 (Tz)</option>
<option value="SA">南非 (SA)</option>
</select>
<!-- 每个国家一组独立的 cityselect -->
<fieldset name="Ug" disabled>
<label for="cityselect-Ug">选择城市:</label>
<select class="form-control-selector" name="cityselect" required>
<option value="" selected>- 选择城市</option>
<option value="A">坎帕拉 (A)</option>
<option value="B">金贾 (B)</option>
</select>
</fieldset>
<fieldset name="Ke" disabled>
<label for="cityselect-Ke">选择城市:</label>
<select class="form-control-selector" name="cityselect" required>
<option value="" selected>- 选择城市</option>
<option value="C">内罗毕 (C)</option>
<option value="D">蒙巴萨 (D)</option>
</select>
</fieldset>
<fieldset name="Rw" disabled>
<label for="cityselect-Rw">选择城市:</label>
<select class="form-control-selector" name="cityselect" required>
<option value="" selected>- 选择城市</option>
<option value="E">基加利 (E)</option>
<option value="F">鲁亨盖里 (F)</option>
</select>
</fieldset>
<fieldset name="Tz" disabled>
<label for="cityselect-Tz">选择城市:</label>
<select class="form-control-selector" name="cityselect" required>
<option value="" selected>- 选择城市</option>
<option value="G">达累斯萨拉姆 (G)</option>
<option value="H">阿鲁沙 (H)</option>
</select>
</fieldset>
<fieldset name="SA" disabled>
<label for="cityselect-SA">选择城市:</label>
<select class="form-control-selector" name="cityselect" required>
<option value="" selected>- 选择城市</option>
<option value="I">约翰内斯堡 (I)</option>
<option value="J">开普敦 (J)</option>
</select>
</fieldset>
</form>
<script>
document.forms.form01.countryselect.addEventListener('change', function(e) {
const form = e.target.form;
// 禁用所有 fieldset
[...form.elements]
.filter(el => el.nodeName === 'FIELDSET')
.forEach(el => el.disabled = true);
// 启用匹配的 fieldset(name 与选中值一致)
if (this.value && form[this.value]) {
form[this.value].disabled = false;
}
});
</script>⚠️ 注意事项与最佳实践
-
name 属性必须严格匹配:
<select name="countryselect"></select>的选中值(如"Ug")需与<fieldset name="Ug"></fieldset>的name完全一致(区分大小写); -
避免重复 ID:本方案不依赖
id,故多个name="cityselect"是安全且合法的(浏览器仅提交已启用字段); -
无障碍增强:为每个
<select></select>添加<label></label>,提升屏幕阅读器支持; -
默认状态处理:初始时所有 fieldset 为
disabled,确保用户首次进入页面时无冗余选项; -
扩展性友好:新增国家只需添加
<option></option>和对应<fieldset></fieldset>,无需修改 JS 逻辑。
该方案轻量、健壮、符合 HTML 标准,无需 jQuery 或外部库,适用于现代浏览器及主流表单验证流程。

















