如何用jQuery创建动态多级下拉菜单?基于JSON填充树形结构
嘿,这个需求我熟!用jQuery实现这种支持多层级的动态下拉菜单,核心就是先把扁平的JSON转成树形结构,再递归生成对应的HTML元素就行。我给你一步步拆解,保证能搞定:
第一步:把扁平JSON转成树形结构
你的原始数据是扁平的,每个节点只知道自己的父ID,我们得先把它转成嵌套的树形结构,这样后续递归遍历起来才方便。写个工具函数就能搞定:
function buildTree(data) { const tree = []; const nodeMap = {}; // 先把所有节点存入Map,方便快速查找 data.forEach(item => { const node = { id: item.Record.PrefcatID, parentId: item.Record.parentid, name: item.Record.prefname, children: [] }; nodeMap[node.id] = node; }); // 把每个节点挂载到对应的父节点下 data.forEach(item => { const currentNode = nodeMap[item.Record.PrefcatID]; if (currentNode.parentId === "0") { // parentid为0的是根节点,直接加入树形数组 tree.push(currentNode); } else { // 找到父节点,把当前节点加入父节点的children数组 const parentNode = nodeMap[currentNode.parentId]; if (parentNode) parentNode.children.push(currentNode); } }); return tree; }
第二步:递归生成多级下拉菜单的HTML
这里有两种常用的实现方式,你可以根据需求选:
方式一:用<optgroup>分组(层级清晰,适合父节点仅做分类的场景)
这种方式会把子菜单放到父节点对应的<optgroup>里,原生select自带分组样式:
function renderOptgroupMenu(tree, $selectElement) { function renderNodes(nodes, $parent) { nodes.forEach(node => { if (node.children.length > 0) { // 创建optgroup作为分组容器 const $optgroup = $('<optgroup>').attr('label', node.name); $parent.append($optgroup); // 递归渲染子节点 renderNodes(node.children, $optgroup); } else { // 没有子节点的话,直接创建option const $option = $('<option>').val(node.id).text(node.name); $parent.append($option); } }); } renderNodes(tree, $selectElement); }
方式二:给选项加缩进(所有节点都可选中,用缩进体现层级)
如果你的需求是所有层级的节点都能被选中,这种方式更合适,通过添加空格缩进区分层级:
function renderIndentedMenu(tree, $selectElement, indent = '') { tree.forEach(node => { // 创建带缩进的option const $option = $('<option>').val(node.id).html(`${indent}${node.name}`); $selectElement.append($option); // 递归渲染子节点,缩进量加倍 if (node.children.length > 0) { renderIndentedMenu(node.children, $selectElement, indent + ' '); } }); }
第三步:整合代码,用jQuery渲染到页面
假设你的页面上有一个空的select容器:
<select id="multiLevelDropdown"></select>
然后把所有逻辑整合起来,在页面加载完成后执行:
$(document).ready(function() { // 你的原始JSON数据(如果是后端接口获取,换成ajax请求即可) const rawData = [ {"Key":"001","Record":{"PrefcatID":"001","parentid":"0","prefname":"org1"}}, {"Key":"002","Record":{"PrefcatID":"002","parentid":"0","prefname":"org2"}}, {"Key":"003","Record":{"PrefcatID":"003","parentid":"0","prefname":"org3"}}, {"Key":"004","Record":{"PrefcatID":"004","parentid":"001","prefname":"suborg1"}}, // 剩下的节点数据... ]; // 构建树形结构 const treeData = buildTree(rawData); // 获取页面上的select元素 const $dropdown = $('#multiLevelDropdown'); // 二选一:用optgroup方式渲染 renderOptgroupMenu(treeData, $dropdown); // 或者用缩进方式渲染 // renderIndentedMenu(treeData, $dropdown); });
额外小提示
如果你的数据是从后端异步获取的,只需要把rawData换成ajax请求的返回值就行,比如:
$.ajax({ url: '/your-api-url', dataType: 'json', success: function(response) { const treeData = buildTree(response); renderOptgroupMenu(treeData, $('#multiLevelDropdown')); } });
内容的提问来源于stack exchange,提问作者btc user
相关产品推荐
相关产品推荐

