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

如何实现支持无限层级嵌套的DataTables?

DataTables无限层级嵌套行实现方案

需求说明

需要实现支持无限层级嵌套的DataTables:点击行前的展开按钮可显示子表格,子表格的行同样支持展开/收起操作,以此类推实现无限层级的嵌套结构。

核心实现思路

  1. 递归数据结构:每个数据节点包含details字段,用于存储当前行的子级数据,天然支持无限嵌套
  2. 通用表格初始化函数:封装可复用的表格创建逻辑,递归处理子表格的初始化流程
  3. 事件委托处理:利用事件委托绑定展开/收起事件,避免为每个动态创建的子表格重复绑定事件
  4. 唯一ID管理:维护全局计数器,确保每个嵌套表格的ID唯一,避免DOM元素冲突

完整代码示例

HTML 结构

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css">
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
    <style>
        .details td {
            border-left: 2px solid #ddd;
            padding-left: 20px;
        }
        .control img {
            cursor: pointer;
        }
    </style>
</head>
<body>
    <table id="mainTable" class="display" style="width:100%">
        <thead>
            <tr>
                <th></th>
                <th>Race</th>
                <th>Year</th>
                <th>Total</th>
            </tr>
        </thead>
    </table>
</body>
</html>

JavaScript 代码

// 全局计数器,确保每个子表格ID唯一
let tableCounter = 1;

// 生成嵌套表格的HTML结构
function generateSubTableHtml(tableId) {
    return `<table id="subTable_${tableId}" class="display" style="width:100%"></table>`;
}

// 通用表格初始化函数,支持递归创建嵌套表格
function initTable(tableSelector, data, columns, isMainTable = false) {
    const table = $(tableSelector).DataTable({
        data: data,
        paging: false,
        ordering: true,
        info: true,
        columns: columns,
        columnDefs: isMainTable ? [] : [
            // 子表格的图片列渲染
            {
                targets: 1,
                render: function(data) {
                    return `<img width="80px" src="${data}" alt="Player">`;
                }
            }
        ],
        rowCallback: function(row, rowData) {
            // 仅当当前行有子数据时,添加展开按钮
            if (rowData.details && rowData.details.length > 0) {
                $(row).find('td:first-child').html('<img src="https://i.imgur.com/SD7Dz.png" alt="Expand">');
            } else {
                $(row).find('td:first-child').html('');
            }
        }
    });

    // 事件委托绑定展开/收起事件,支持动态创建的表格
    $(tableSelector).on('click', 'td.control img', function() {
        const tr = $(this).closest('tr');
        const row = table.row(tr);
        const rowData = row.data();

        if (row.child.isShown()) {
            // 收起子表格
            this.src = 'https://i.imgur.com/SD7Dz.png';
            row.child.hide();
            tr.removeClass('shown');
        } else {
            // 展开子表格
            this.src = 'https://i.imgur.com/d4ICC.png';
            const subTableId = tableCounter++;
            const subTableHtml = generateSubTableHtml(subTableId);
            row.child(subTableHtml, 'details').show();
            tr.addClass('shown');

            // 递归初始化子表格
            initTable(`#subTable_${subTableId}`, rowData.details, [
                { data: null, className: 'control', orderable: false },
                { data: 'pic' },
                { data: 'name' },
                { data: 'team' },
                { data: 'server' }
            ]);
        }
    });

    return table;
}

// 递归结构的测试数据(可无限添加嵌套层级)
const terranImage = "https://i.imgur.com/HhCfFSb.jpg"; 
const jaedongImage = "https://i.imgur.com/s3OMQ09.png";
const grubbyImage = "https://i.imgur.com/wnEiUxt.png";
const stephanoImage = "https://i.imgur.com/vYJHVSQ.jpg";
const scarlettImage = "https://i.imgur.com/zKamh3P.jpg";

// 三级嵌套数据示例
const level3Data = [{ 
    pic: terranImage, 
    name: "Bomber", 
    team: "independent", 
    server: "NA",
    details: [] // 可继续添加子数据实现更深层级
}];

const level2Data = [
    { 
        pic: jaedongImage, 
        name: "Jaedong", 
        team: "evil geniuses", 
        server: "NA",
        details: level3Data
    },
    { 
        pic: scarlettImage, 
        name: "Scarlett", 
        team: "acer", 
        server: "Europe",
        details: []
    },
    { 
        pic: stephanoImage, 
        name: "Stephano", 
        team: "evil geniuses", 
        server: "Europe",
        details: []
    }
];

const mainData = [
    { 
        race: "Zerg", 
        year: "2014", 
        total: "3", 
        details: level2Data
    },
    { 
        race: "Protoss", 
        year: "2014", 
        total: "1", 
        details: [{
            pic: grubbyImage, 
            name: "Grubby", 
            team: "independent", 
            server: "Europe",
            details: []
        }]
    },
    { 
        race: "Terran", 
        year: "2014", 
        total: "1", 
        details: level3Data
    }
];

// 初始化主表格
$(document).ready(function() {
    initTable('#mainTable', mainData, [
        { data: null, className: 'control', orderable: false },
        { data: 'race' },
        { data: 'year' },
        { data: 'total' }
    ], true);
});

代码关键说明

  1. 递归数据结构:每个数据对象都包含details数组,用于存储子级数据,可无限扩展嵌套层级
  2. 通用初始化函数:initTable函数统一处理表格初始化、行回调、事件绑定,递归创建子表格,避免重复代码
  3. 事件委托:通过$(tableSelector).on('click', 'td.control img', ...)绑定事件,自动适配动态创建的子表格
  4. 唯一ID管理:全局计数器tableCounter确保每个子表格ID唯一,避免DOM元素ID冲突
  5. 动态按钮控制:在rowCallback中根据当前行是否有子数据,动态显示/隐藏展开按钮

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:05:25