如何从同一select下拉框中递归获取所有层级关联依赖选项
实现思路
这个需求本质是多叉树的深度优先遍历,下拉选项里的dependid就是当前节点的父节点ID,dependid="0"的是根节点,选中某个节点后要拿到它所有层级的后代节点。
如果每次递归都遍历全量DOM找子节点性能很差,最好初始化时就把父子关系提前存成映射表,后续查找直接读映射即可,不用反复查询DOM。
基础HTML结构
<select class="form-control dropdownlist" id="Location"> <option value="67" dependid="17">Amsterdam</option> <option value="1" dependid="0">APAC</option> <option value="20" dependid="3">Argentina</option> <option value="23" dependid="4">Arizona</option> <option value="40" dependid="26">Atlanta</option> <option value="47" dependid="31">Austin</option> <option value="5" dependid="1">Australia</option> <option value="12" dependid="2">Austria</option> <option value="54" dependid="8">Bangalore</option> <option value="61" dependid="74">Bangkok</option> <option value="69" dependid="19">Brighton</option> <option value="71" dependid="20">Buenos Aires</option> <option value="24" dependid="4">California</option> <option value="21" dependid="3">Canada</option> <option value="25" dependid="4">Canada - Cloud5</option> <option value="41" dependid="27">Chicago</option> <option value="6" dependid="1">China</option> <option value="48" dependid="31">Dallas</option> <option value="2" dependid="0">EMEA</option> <option value="75" dependid="4">Florida</option> <option value="15" dependid="2">France</option> <option value="63" dependid="13">Frankfurt</option> <option value="26" dependid="4">Georgia</option> <option value="13" dependid="2">Germany</option> <option value="55" dependid="8">Gurgaon</option> <option value="7" dependid="1">Hong Kong</option> <option value="27" dependid="4">Illinois</option> <option value="8" dependid="1">India</option> <option value="16" dependid="2">Italy</option> <option value="37" dependid="75">Jacksonville</option> <option value="9" dependid="1">Japan</option> <option value="3" dependid="0">LACC</option> <option value="42" dependid="76">Las Vegas</option> <option value="70" dependid="19">London</option> <option value="35" dependid="24">Los Angeles</option> <option value="64" dependid="14">Madrid</option> <option value="22" dependid="3">Mexico</option> <option value="73" dependid="22">Mexico City</option> <option value="56" dependid="8">Mumbai</option> <option value="46" dependid="30">Nashville</option> <option value="17" dependid="2">Netherlands</option> <option value="76" dependid="4">Nevada</option> <option value="28" dependid="4">New York</option> <option value="43" dependid="28">New York</option> <option value="38" dependid="75">Orlando</option> <option value="57" dependid="9">Osaka</option> <option value="29" dependid="4">Pennsylvania</option> <option value="44" dependid="29">Philadelphia</option> <option value="34" dependid="23">Phoenix</option> <option value="66" dependid="16">Rome</option> <option value="65" dependid="15">Rueil Malmaison</option> <option value="36" dependid="25">Saint John</option> <option value="49" dependid="32">Salt Lake City</option> <option value="50" dependid="33">Seattle</option> <option value="52" dependid="6">Shanghai</option> <option value="10" dependid="1">Singapore</option> <option value="59" dependid="10">Singapore</option> <option value="14" dependid="2">Spain </option> <option value="68" dependid="18">Stockholm</option> <option value="39" dependid="75">Sunrise</option> <option value="18" dependid="2">Sweden/Finland</option> <option value="51" dependid="5">Sydney</option> <option value="53" dependid="7">Taikoo Shing</option> <option value="60" dependid="11">Taipei</option> <option value="11" dependid="1">Taiwan</option> <option value="30" dependid="4">Tennessee</option> <option value="31" dependid="4">Texas</option> <option value="74" dependid="1">Thailand</option> <option value="58" dependid="9">Tokyo</option> <option value="72" dependid="21">Toronto</option> <option value="19" dependid="2">United Kingdom</option> <option value="4" dependid="0">US</option> <option value="32" dependid="4">Utah</option> <option value="62" dependid="12">Vienna</option> <option value="33" dependid="4">Washington</option> <option value="45" dependid="29">Wilkes-Barre</option> </select>
具体实现代码
// 初始化阶段构建映射,页面加载后只需要执行一次 const selectEl = document.getElementById('Location'); // 存储所有选项基础信息,key为option的value属性值 const optionInfoMap = new Map(); // 存储父子关系映射,key为父节点value,value为所有子节点value组成的数组 const parentToChildrenMap = new Map(); Array.from(selectEl.options).forEach(opt => { const val = opt.value; const parentId = opt.getAttribute('dependid'); optionInfoMap.set(val, { value: val, label: opt.textContent.trim(), parentId: parentId }); if (!parentToChildrenMap.has(parentId)) { parentToChildrenMap.set(parentId, []); } parentToChildrenMap.get(parentId).push(val); }); /** * 递归获取选中项的所有层级关联后代 * @param {string} selectedValue 选中的选项value * @returns {Array} 所有关联项列表 */ function getAllDescendants(selectedValue) { const result = []; // 深度优先遍历 const traverse = (currentVal) => { const childVals = parentToChildrenMap.get(currentVal) || []; childVals.forEach(childVal => { result.push(optionInfoMap.get(childVal)); // 递归遍历下一级子节点 traverse(childVal); }); }; traverse(selectedValue); return result; } // 绑定下拉框选择事件 selectEl.addEventListener('change', function() { const currentSelected = optionInfoMap.get(this.value); const allRelated = getAllDescendants(this.value); console.log('当前选中项:', currentSelected); console.log('所有关联项:', allRelated); });
逻辑说明
- 不需要额外写遍历终止判断:
dependid=0的根节点没有上层父节点,也不会有节点的dependid指向不存在的value,当某个节点没有子节点时,读取到的子节点列表是空数组,递归会自动终止。 - 选中value为1的APAC选项测试时,会正确返回所有下属的国家、城市层级数据:既包含Australia、China等一级关联项,也会继续向下找到Sydney、Shanghai等二级关联项,不会出现层级遗漏。
- 提前构建映射的方式比每次递归都遍历DOM查找子节点性能高很多,选项量级大的时候优势非常明显。
内容的提问来源于stack exchange,提问作者Vishvadeep singh
相关产品推荐
相关产品推荐

