You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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 + '&nbsp;&nbsp;');
        }
    });
}
第三步:整合代码,用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:03:11