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

如何动态生成带可折叠ul/li标签的多列树形列表

可折叠树列表复选框独立列布局方案

问题核心

当前手写的可折叠树列表采用默认流式排版,复选框直接跟在名称后,没有做列分区,既无法对齐,也不方便后续扩展物料规格、数量等更多字段。

基于现有代码的改造方案

改造总思路是给每个列表行加弹性布局,拆分独立列容器,所有层级的列宽保持统一,同时修复点击复选框误触发折叠的问题。

1. 修改节点渲染函数

拆分列表项内容为独立列元素,预留后续扩展列的位置,给复选框加事件阻止冒泡:

function check(obj) {
    let html = '';
    const name = obj.name ? `${obj.name} (${obj.type})` : obj.type;
    html += '<div class="node">'
    html += '<li class="ntitle">';
    // 名称列:放折叠图标+部件名称
    html += '  <span class="col name-col">';
    html += '    <span class="expand-icon"></span>';
    html +=      name;
    html += '  </span>';
    // 复选框列:固定宽度,阻止点击冒泡
    html += '  <span class="col check-col">';
    html += `    <input type="checkbox" name="${obj.id-id}" value="checked" onchange="snap(this)" onclick="event.stopPropagation()"/>`;
    html += '  </span>';
    // 后续新增列直接在此处追加即可,示例:
    // html += `  <span class="col spec-col">${obj.spec || '-'}</span>`;
    // html += `  <span class="col qty-col">${obj.qty || 0}</span>`;
    html += '</li>';

    if (obj.children?.length) {
        html += '<ul class="children hide">';
        obj.children.forEach(child => html += check(child));
        html += '</ul>';
    }
    html += "</div>";
    return html;
}

2. 补充CSS布局样式

用Flex实现多列对齐,统一所有层级的缩进和列宽,折叠图标用内置SVG不用额外图片资源:

.objtree * {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}
/* 列表行弹性布局 */
.ntitle {
    list-style: none;
    display: flex;
    align-items: center;
    min-height: 36px;
    cursor: pointer;
    border-bottom: 1px solid #eee;
}
/* 通用列样式 */
.col {
    padding: 0 8px;
}
/* 名称列自适应宽度 */
.name-col {
    flex: 1;
    display: flex;
    align-items: center;
}
/* 复选框列固定宽度,全局对齐 */
.check-col {
    width: 60px;
    text-align: center;
}
/* 折叠展开图标 */
.expand-icon {
    width: 16px;
    height: 16px;
    margin-right: 6px;
    flex-shrink: 0;
    background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23666"><path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"/></svg>') center/contain no-repeat;
    transition: transform .2s ease;
}
/* 展开状态图标旋转90度 */
.ntitle.open .expand-icon {
    transform: rotate(90deg);
}
/* 子列表缩进,和父级名称对齐 */
.children {
    padding-left: 26px;
}
.children.hide {
    display: none;
}
/* 无子节点的项保留图标占位,保证列对齐 */
.node:not(:has(.children)) .expand-icon {
    visibility: hidden;
}

3. 优化事件绑定逻辑

改用事件委托,动态渲染的节点不需要重复绑定事件:

function assignEvent() {
    $('.objtree')
        .off('click', '.ntitle')
        .on('click', '.ntitle', function () {
            const $childList = $(this).parent().find('.children:first');
            $(this).toggleClass('open');
            $childList.toggleClass('hide');
        })
}

更优的长期方案

如果后续树结构层级更深、列数更多,或者需要支持搜索、筛选、节点拖拽等能力,不建议继续维护手写列表,直接用成熟的**树形表格(TreeGrid)**组件即可:

  • 主流UI库(Ant Design、Element UI、Layui等)都自带开箱即用的树形表格组件,原生支持多列对齐、复选框选择、固定列、自定义单元格模板
  • 组件内部已经处理好了缩进对齐、事件冒泡、性能优化等问题,不需要手动维护布局逻辑,扩展性远强于手写的列表结构

效果参考

  • 现有效果
    现有效果
  • 目标效果
    目标效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:01:14