15

Angular Material CDK 树组件文档说:

“扁平树通常更容易设计和检查。它们对滚动变化也更友好,例如无限或虚拟滚动

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

我有一棵巨大的树要渲染,现在它太慢了,当我递归打开所有节点时,它会崩溃

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

4

2 回答 2

15

我知道这是旧的,但我在试图找出相同的确切事物时遇到了这个线程,经过大量实验,我已经找到了一个虚拟滚动平面树的基本工作示例,如果你已经需要非常小的修改有一个工作的 cdk-tree

我的解决方案的关键是放弃 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 中模板代码的差异,您会发现它并没有那么糟糕。

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

于 2019-11-13T21:47:54.447 回答
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>

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

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

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

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

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

于 2019-01-06T12:38:39.187 回答