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

时间:2018-10-02 10:26:17

标签: angular angular6 angular-material2 angular-cdk

Angular Material CDK树组件文档说:

“平整的树通常更易于样式设置和检查。它们也更易于滚动变化,例如无限滚动或虚拟滚动

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

我有一棵大树要渲染,现在它是如此之慢,当我递归打开所有节点时,它将崩溃

我尝试了 @ angular / cdk-experimental,但没有弄清楚如何将其与树组件集成

3 个答案:

答案 0 :(得分:4)

我知道这很老了,但是我在尝试找出相同的东西时遇到了这个线程,经过大量的实验,我找到了一个虚拟滚动树的基本工作示例,该树需要如果您已经有一个可用的cdk树,则非常小修改

我的解决方案的关键是放弃cdk-tree指令,直接将我的MatTreeFlatDataSource和FlatTreeControl与* cdkVirtualFor一起使用。您可能已经设置了这些对象,以将其作为输入传递到cdk-tree中。 cdk-tree实际上只是围绕着这两个正在完成所有繁重工作的对象的非常轻巧的包装。

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

这里包含的内容:

  • 从同一基础数据源中提取并由同一基础树控件控制的两个滚动的扁平树(即,它们拥有相同的数据,您对一棵树所做的任何操作都将反映在另一棵树中,很好)

  • 第一棵树使用cdk-tree指令,但是我不知道如何使它与CDK虚拟滚动条配合使用,因此它呈现 all 个节点

    < / li>
  • 第二棵树不使用cdk-tree,但是我能够进行虚拟滚动,而只需很少的更改就可以正常工作。结果,您必须自己进行样式设计和一些基本的逻辑,但是如果您查看stackblitz中模板代码的不同,您会发现它还不错。

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

答案 1 :(得分:1)

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

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

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

要获得与树的基本虚拟滚动,请将其添加到模板中:

<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)
    })
  }

我们订阅renderedRangeStream,每当滚动更改时,该{{1}}都会发出一个范围。每当发生这种情况时,我们只需将数据源设置为等于适当的分片即可!

Stackblitz with result希望这足以让您入门!

答案 2 :(得分:0)

  • npm install @angular/cdk@7.0.0ng add @angular/cdk@7.0.0
  • 将滚动模块导入到您的应用app.module.ts
    • import { ScrollingModule } from '@angular/cdk/scrolling';
    • 在@ngmodule内的导入中
    • 添加ScrollingModule
  • 在HTML文件中添加cdk-virtual-scroll-viewport

<cdk-virtual-scroll-viewport  style="height: 250px" itemSize="50" >
//your code will be here
    
</cdk-virtual-scroll-viewport>