Документация по компоненту дерева 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.info(range, 'range')
this.dataSource.data = this.fullDatasource.slice(range.start, range.end)
})
}
Мы подписываемся на renderedRangeStream, который выдает диапазон при каждом изменении прокрутки. Каждый раз, когда это происходит, мы просто устанавливаем источник данных равным соответствующему срезу!
Stackblitz с результатом Надеюсь, этого достаточно, чтобы вы начали!
не могли бы вы заглянуть в это stackoverflow.com/questions/56064233/…
Небольшая проблема с этим подходом: renderedRangeStream работает вне зоны Angular, поэтому у вас могут возникнуть проблемы с обнаружением изменений на отрисованных узлах дерева. Вы можете решить эту проблему, внедрив CdkVirtualForOf в качестве дочернего представления и подписавшись вместо этого на его наблюдаемый объект viewChange.
Одна проблема, которую я вижу в этом подходе, заключается в том, что дерево матов может быть рекурсивным, в то время как этот метод просто сокращает длину корневых элементов. если на втором уровне много элементов, такой подход вообще не поможет с прокруткой.
npm install @angular/[email protected] или ng add @angular/[email protected]app.module.tsimport { ScrollingModule } from '@angular/cdk/scrolling';ScrollingModule в импорт внутри @ngmodulecdk-virtual-scroll-viewport в файл HTML<cdk-virtual-scroll-viewport style = "height: 250px" itemSize = "50" >
//your code will be here
</cdk-virtual-scroll-viewport>Я знаю, что это устарело, но я наткнулся на эту тему, пытаясь выяснить то же самое, и после долгих экспериментов я выяснил базовый рабочий пример виртуально прокручиваемого плоского дерева, для которого требуется ОЧЕНЬ МАЛЕНЬКАЯ МОДИФИКАЦИЯ, если у вас уже есть работающее дерево 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, поэтому он отображает все узлов
Второе дерево НЕ использует cdk-tree, но мне удалось заставить виртуальную прокрутку работать чисто с очень небольшими изменениями. В результате вам придется самостоятельно выполнять стили и некоторую базовую логику, но если вы посмотрите на разницу в коде шаблона в stackblitz, вы увидите, что это не так уж и плохо.
Я показываю количество узлов, отображаемых каждым контейнером прокрутки, чтобы продемонстрировать, что виртуальная прокрутка работает в одном, а не в другом.
отличный ответ, но будьте осторожны, если, как и я, у вас есть узлы рендеринга пользовательских компонентов: <cdk-virtual-scroll-viewport> <my-node *cdkVirtualFor = "let node of dataSource" [node] = "node"><my-node> </cdk-virtual-scroll-viewport> ... приводит к тому, что cdk-virtual-scroll-content-wrapper имеет flex-direction: row;, обеспечивающий горизонтальную прокрутку за пределами области просмотра. Обертывание <my-node> в <div> исправило это: <cdk-virtual-scroll-viewport> <div *cdkVirtualFor = "let node of dataSource"> <my-node [node] = "node"><my-node> </div> </cdk-virtual-scroll-viewport>
Наконец я нашел решение. Оно работает! Пришло время реализовать детали из обычного дерева, которое имеет большой функционал, так что, возможно, возникнут какие-то неприятности.
Меня тоже интересует эта тема. Для этого не хватает документации ... Я почти уверен, что для знатоков это просто