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

如何遍历嵌套对象内部列表并实现层级展开折叠展示

通用嵌套对象层级遍历与可折叠表格实现

核心思路

  • 用递归遍历替代固定层级的foreach,只要对象包含Items子列表属性,就自动向下遍历,适配任意嵌套深度
  • 后端负责统一整理所有层级的对象数据,标记层级、是否含子节点;前端负责渲染表格并实现展开/折叠交互

后端递归遍历示例(C#)

先定义通用节点结构,用来传递给前端:

public class TreeNode
{
    public string ObjectType { get; set; } // 类名,如"A""B"
    public string ObjectInfo { get; set; } // 对象展示信息,可自定义拼接属性
    public int Level { get; set; } // 层级,用于前端缩进
    public bool HasChildren { get; set; } // 是否存在子节点
    public List<TreeNode> Children { get; set; } = new List<TreeNode>();
}

// 核心递归遍历方法
public List<TreeNode> TraverseNestedObjects(object root, int level = 0)
{
    var nodes = new List<TreeNode>();
    
    // 生成当前节点信息
    var currentNode = new TreeNode
    {
        ObjectType = root.GetType().Name,
        ObjectInfo = GetObjectDisplayText(root),
        Level = level,
        HasChildren = HasItemsProperty(root)
    };
    nodes.Add(currentNode);
    
    // 递归遍历子节点(如果存在Items)
    if (currentNode.HasChildren)
    {
        var items = GetItemsValue(root);
        foreach (var item in items)
        {
            nodes.AddRange(TraverseNestedObjects(item, level + 1));
        }
    }
    
    return nodes;
}

// 辅助方法:判断对象是否有Items属性
private bool HasItemsProperty(object obj)
{
    return obj.GetType().GetProperty("Items") != null;
}

// 辅助方法:获取Items属性的值
private IEnumerable<object> GetItemsValue(object obj)
{
    var prop = obj.GetType().GetProperty("Items");
    return prop?.GetValue(obj) as IEnumerable<object> ?? Enumerable.Empty<object>();
}

// 辅助方法:自定义对象展示文本(可按需修改)
private string GetObjectDisplayText(object obj)
{
    // 示例:拼接除Items外的所有公共属性
    var props = obj.GetType().GetProperties()
                   .Where(p => p.Name != "Items")
                   .Select(p => $"{p.Name}: {p.GetValue(obj)}");
    return string.Join(", ", props);
}

前端可折叠表格实现(HTML+JS)

将后端返回的TreeNode列表渲染为可折叠表格:

<style>
    .indent { margin-left: 20px; }
    .collapse-btn { cursor: pointer; color: #0066cc; text-decoration: underline; }
    .child-row { display: none; }
</style>

<table border="1" cellpadding="8" width="100%">
    <thead>
        <tr>
            <th>操作</th>
            <th>层级</th>
            <th>类类型</th>
            <th>对象详情</th>
        </tr>
    </thead>
    <tbody id="treeTable">
        <!-- 后端渲染内容插入此处 -->
    </tbody>
</table>

<script>
    // 替换为后端返回的JSON节点数据
    const treeNodes = /* 后端接口返回的TreeNode列表JSON */;

    // 渲染表格
    function renderTreeTable() {
        const tbody = document.getElementById('treeTable');
        tbody.innerHTML = '';

        treeNodes.forEach(node => {
            const row = document.createElement('tr');
            row.dataset.level = node.level;
            row.dataset.hasChildren = node.hasChildren;

            // 操作列:展开/折叠按钮
            const actionTd = document.createElement('td');
            if (node.hasChildren) {
                const btn = document.createElement('span');
                btn.className = 'collapse-btn';
                btn.textContent = '+';
                btn.onclick = () => toggleChildRows(node.level);
                actionTd.appendChild(btn);
            }
            row.appendChild(actionTd);

            // 层级列
            const levelTd = document.createElement('td');
            levelTd.textContent = node.level;
            row.appendChild(levelTd);

            // 类类型列(带缩进)
            const typeTd = document.createElement('td');
            typeTd.innerHTML = `<span class="indent" style="margin-left: ${node.level * 20}px">${node.objectType}</span>`;
            row.appendChild(typeTd);

            // 对象详情列
            const infoTd = document.createElement('td');
            infoTd.textContent = node.objectInfo;
            row.appendChild(infoTd);

            // 非根节点默认隐藏
            if (node.level > 0) {
                row.classList.add('child-row');
            }

            tbody.appendChild(row);
        });
    }

    // 切换子节点显示/隐藏
    function toggleChildRows(parentLevel) {
        const childRows = document.querySelectorAll(`tr[data-level="${parentLevel + 1}"]`);
        const parentBtn = document.querySelector(`tr[data-level="${parentLevel}"] .collapse-btn`);
        
        childRows.forEach(row => {
            row.style.display = row.style.display === 'none' ? '' : 'none';
            // 递归切换更深层级(可选,按需开启)
            if (row.dataset.hasChildren === 'true') {
                const childBtn = row.querySelector('.collapse-btn');
                childBtn.textContent = row.style.display === 'none' ? '+' : '-';
                toggleChildRows(parseInt(row.dataset.level));
            }
        });

        // 更新父节点按钮符号
        parentBtn.textContent = parentBtn.textContent === '+' ? '-' : '+';
    }

    // 初始化渲染
    renderTreeTable();
</script>

关键说明

  • 递归通用性:无论嵌套层级是A→B→C→D还是更深,递归逻辑都会自动遍历所有节点,无需修改遍历代码
  • 交互逻辑:通过节点level属性区分层级,控制缩进范围;点击按钮时切换对应子层级的显示状态
  • 扩展性:后端GetObjectDisplayText可自定义对象展示内容,前端样式可按需调整缩进、按钮样式等

内容的提问来源于stack exchange,提问作者Dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 19:13:12