
本文介绍如何实现两个关联下拉菜单,使第一个下拉框(国家)的选择实时控制第二个下拉框(城市)的可选项,采用语义化、可维护的 fieldset 分组 + 原生 javascript 方案,避免 jquery 依赖与 dom 频繁操作。
本文介绍如何实现两个关联下拉菜单,使第一个下拉框(国家)的选择实时控制第二个下拉框(城市)的可选项,采用语义化、可维护的 fieldset 分组 + 原生 javascript 方案,避免 jquery 依赖与 dom 频繁操作。
在表单开发中,「级联选择」(Cascading Select)是常见需求——例如先选国家,再根据所选国家动态加载对应的城市或地区列表。传统做法常通过 empty() + append() 动态重写 <option></option>,但易出错、难维护,且忽略表单语义与无障碍支持。本文推荐一种更健壮、语义清晰的替代方案:利用 <fieldset></fieldset> 分组 + disabled 属性控制可见性与提交行为。
✅ 核心思路
- 每个国家对应一个独立的
<fieldset></fieldset>,内含专属的<select name="cityselect"></select>; - 所有 fieldset 初始设为
disabled,配合 CSS 隐藏(display: none); - 当用户切换国家时,仅启用匹配
name的 fieldset,其余保持禁用; - 关键优势:禁用的 fieldset 及其子元素不会参与表单提交,无需手动清空或校验值,天然符合 HTML 表单规范。
? 完整实现代码
<form name="form01">
<label for="countryselect">选择国家:</label>
<select class="form-control-selector" id="countryselect" 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>
<!-- 每个国家一个 fieldset,name 与 countryselect 的 option value 严格一致 -->
<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>
<style>
fieldset {
border: none;
margin-top: 0.5rem;
}
fieldset:disabled {
display: none;
}
/* 可选:增强可访问性 */
fieldset:not(:disabled) label {
font-weight: bold;
}
</style>
<script>
document.forms.form01.countryselect.addEventListener('change', function (e) {
const form = e.target.form;
// 禁用所有 fieldset
[...form.elements]
.filter(el => el.nodeName === 'FIELDSET')
.forEach(fs => fs.disabled = true);
// 启用匹配当前国家值的 fieldset
if (this.value && form[this.value]) {
form[this.value].disabled = false;
}
});
</script>⚠️ 注意事项与最佳实践
-
name必须严格一致:<fieldset name="Ug"></fieldset>与<option value="Ug"></option>的值必须完全相同(区分大小写),否则form[this.value]查找失败; -
默认状态处理:初始时所有 fieldset 为
disabled,确保未选择国家前无城市可选,符合业务逻辑; -
无障碍友好:
<label></label>显式绑定、fieldset语义化分组,利于屏幕阅读器识别; -
表单提交安全:禁用的 fieldset 内部控件自动被排除在
FormData和form.submit()之外,无需额外校验; -
扩展性强:新增国家只需添加
<option></option>和对应<fieldset></fieldset>,逻辑零侵入; -
兼容性:纯原生 JS,支持所有现代浏览器(IE11+ 需微调
for...of或使用Array.from())。
该方案摒弃了易错的 DOM 操作,转而利用 HTML 原生能力实现高效、可维护、语义正确的级联交互,是生产环境中的推荐实践。

















