首页 > 解决方案 > 将现有的 ng-container 树适配为虚拟树

问题描述

我有一个非常非常裸露的最小树,有时需要渲染成千上万的元素。这会导致一些非常糟糕的性能,因此该网站变得相当滞后。相反,我选择尝试cdk-virtual-scroll-viewport,但我无法让它工作,因为我正在使用ngTemplateOutlet. 例子:

<ul>
    <ng-template #recursiveList let-root>
        <li *ngFor="let item of root; trackBy:item?.id">

            <!-- Show the actual elements, including + and - to expand/contract the tree -->

            <ul [ngClass]="item?.expanded ? '' : 'hide'" *ngIf="item?.children && item?.children.length > 0">
                <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item?.children }"></ng-container>
            </ul>
        </li>
    </ng-template>
    <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: root }"></ng-container>
</ul>

我的root数组看起来有点像这样:

[{
  id: "aec04ef4-fc6a-481f-a12d-0ce987d494b3",
  expanded: true,
  children: [{
    id: "cbf9e862-e932-410f-ad84-ed0a5ec1917a",
    expanded: false,
    children: []
  }]
}]

我试着简单地这样做:

<ul>
    <ng-template #recursiveList let-root>
        <li *cdkVirtualFor="let item of root; trackBy:item?.id">

            <!-- Show the actual elements, including + and - to expand/contract the tree -->

            <ul [ngClass]="item?.expanded ? '' : 'hide'" *ngIf="item?.children && item?.children.length > 0">
                <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item?.children }"></ng-container>
            </ul>
        </li>
    </ng-template>

    <cdk-virtual-scroll-viewport style="height: 750px" itemSize="50">
        <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: root }"></ng-container>
    </cdk-virtual-scroll-viewport>
</ul>

所以基本上添加了cdk-virtual-scroll-viewport元素并使用cdkVirtualFor而不是ngFor,但我收到一条错误消息:

没有 CdkVirtualScrollViewport 的提供者

我猜这是一个错误,因为它尚未关闭:https ://github.com/angular/components/issues/15277

知道如何调整我现有的代码吗?我面临的最大问题是隐藏/取消隐藏部分,因为由于ng-container某种原因它无法使用它。

标签: angularangular7angular-cdk-virtual-scroll

解决方案


在尝试了各种 CDK 虚拟化方法并没有得到满意的结果后,我为此构建了一个自定义组件。

https://github.com/gjcampbell/ooffice/tree/master/projects/of-tree

我建议使用一个库(我的库具有我所知道的最好的性能),或者如果您宁愿坚持当前的路径,那么请执行以下操作:

  1. 在您的数据上,存储层次结构信息,例如每个项目的深度和父项
  2. 递归遍历数据并从分层数据创建平面列表
  3. 呈现没有递归模板的平面列表。使用深度来确定压痕。仅传递给cdkVirtualFor其父项为 null 或展开的项。

推荐阅读