具有虚拟滚动的角度材质CDK树组件

Rag*_*nar 10 angular-material2 angular angular6 angular-cdk

Angular Material CDK树组件文档说:

"平面树通常更容易进行样式和检查.它们对滚动变化也更友好,例如无限或虚拟滚动 "

有关如何将虚拟滚动应用于CDK平面树的任何想法?

我有一个巨大的树来渲染,现在它很慢,当我递归打开所有节点时它会崩溃

我试过<cdk-virtual-scroll-viewport> @ angular/cdk-experimental但是没弄清楚如何将它与树组件集成

小智 13

我知道这很旧,但是我在试图找出完全相同的东西时遇到了这个线程,经过多次实验,我已经找到了一个虚拟滚动扁平树的基本工作示例,如果您已经需要进行非常小的修改有一个可用的 cdk 树

我的解决方案的关键是放弃 cdk-tree 指令并直接将我的 MatTreeFlatDataSource 和 FlatTreeControl 与 *cdkVirtualFor 一起使用。您可能已经将这些对象设置为作为输入传递到 cdk-tree。cdk-tree 实际上只是围绕这两个承担所有繁重工作的对象的轻量级包装。

这是一个stackblitz,一个更具体的例子:https ://stackblitz.com/edit/angular-b5nkkd?file=src/app/app.component.html

这是它包含的内容:

  • 两个滚动的扁平树,它们从相同的底层数据源绘制并由相同的底层树控件控制(即,它们保存相同的数据,您对一棵树所做的任何事情也将反映在另一棵树中)

  • 第一棵树使用 cdk-tree 指令,但我不知道如何让它与 CDK 虚拟滚动一起工作,因此它呈现所有节点

  • 第二棵树不使用 cdk-tree,但我能够让虚拟滚动干净利落地工作,只需很少的更改。因此,您必须自己做样式和一些基本逻辑,但是如果您查看 stackblitz 中模板代码的差异,您会发现它并没有那么糟糕。

  • 我正在显示每个滚动容器正在渲染的节点数,以证明虚拟滚动在一个而不是另一个中工作


Ben*_*dle 5

虚拟视口的主要功能是跟踪滚动事件并通知您当前屏幕上的元素。使用此信息,您可以将树的数据源修改为仅显示在屏幕上的节点。

现在的问题是,视口实际上只适用于高度一致的项目。当您展开树的一个节点时,该节点的高度与其余封闭节点的高度不一致。为了解决这个问题,您可以在节点展开时将子节点添加到虚拟视口的数据源。

现在,我将忽略扩展节点问题。

要使用树进行基本的虚拟滚动,请将其添加到您的模板中:

<cdk-virtual-scroll-viewport itemSize="48" style="height: 200px;">
  <ng-container *cdkVirtualFor="let item of fullDatasource"></ng-container>

  <mat-tree [dataSource]="dataSource" [treeControl]="treeControl">...</mat-tree-node>
  </mat-tree>
</cdk-virtual-scroll-viewport>
Run Code Online (Sandbox Code Playgroud)

我们创建视口,告诉它每个节点的大小。然后我们添加virtualForOf, 传入 fullDatasource 以便视口知道它需要多高。这可能有点作弊,因为我相信 的预期用途virtualForOf是模板包含要滚动的项目,但将其保留为空似乎有效。

唯一剩下的就是确保树的数据源只是完整数据源的可见项。我们将改变我们最初在构造函数中声明它的方式,但这是更令人兴奋的部分:

  ngAfterViewInit() {
    this.virtualScroll.renderedRangeStream.subscribe(range => {
      console.log(range, 'range')
      this.dataSource.data = this.fullDatasource.slice(range.start, range.end)
    })
  }
Run Code Online (Sandbox Code Playgroud)

我们订阅renderedRangeStream每当滚动发生变化时就会发出一个范围。每当发生这种情况时,我们只需将数据源设置为适当的切片即可!

Stackblitz 结果希望这足以让你开始!

  • 我发现这种方法的一个问题是,mat-tree 可以是递归的,而这种方法只会切掉根元素的长度。如果第二层有很多项目,这种方法对滚动根本没有帮助。 (3认同)