Angular MaterialのCDKツリーコンポーネントのドキュメントにはこう書かれています:
"フラットツリーは、スタイルと検査が一般的に簡単です。また、無限または仮想スクロール"
CDKフラットツリーに仮想スクロールを適用する方法はありますか?
レンダリングする大規模なツリーがありますが、現在は非常に遅く、すべてのノードを再帰的に開くとクラッシュします
<cdk-virtual-scroll-viewport> @ angular/cdk-experimentalを試しましたが、ツリーコンポーネントと統合する方法がわかりませんでした
仮想ビューポートの主な機能は、スクロールイベントを追跡し、現在画面上にある要素を通知することです。この情報を使用して、ツリーのデータソースを変更して、画面上にあるノードのみにすることができます。
問題は、現在のところ、ビューポートが実際に機能するのは、高さが一定のアイテムでのみであるということです。ツリーのノードを展開すると、そのノードの高さは他の閉じたノードと一致しません。これを回避するために、ノードが展開されているときはいつでも、子ノードを仮想ビューポートのデータソースに追加できる場合があります。
とりあえず、拡張ノードの問題は無視します。
ツリーで基本的な仮想スクロールを取得するには、これをテンプレートに追加します。
<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
をサブスクライブします。それが発生するときはいつでも、データソースを適切なスライスに設定するだけです!
Stackblitzと結果 うまくいけば、これで開始できます!
npm install @angular/[email protected]
またはng add @angular/[email protected]
app.module.ts
import { ScrollingModule } from '@angular/cdk/scrolling';
ScrollingModule
を追加cdk-virtual-scroll-viewport
を追加します<cdk-virtual-scroll-viewport style="height: 250px" itemSize="50" >
//your code will be here
</cdk-virtual-scroll-viewport>