Компонент дерева CDK Angular Material с виртуальной прокруткой

Документация по компоненту дерева Angular Material CDK гласит:

«Плоские деревья, как правило, легче стилизовать и проверять. Они также более удобны для вариантов прокрутки, таких как бесконечность или виртуальная прокрутка»

Есть идеи, как применить виртуальную прокрутку к плоскому дереву CDK?

У меня есть массивное дерево для рендеринга, и сейчас оно настолько медленное, и когда я рекурсивно открываю все узлы, оно вылетает

Я попробовал <cdk-virtual-scroll-viewport> @ angular / cdk-experimental, но не понял, как интегрировать его с компонентом дерева

Меня тоже интересует эта тема. Для этого не хватает документации ... Я почти уверен, что для знатоков это просто

Alexander Kondaurov 06.12.2018 17:45
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
15
1
8 692
3

Ответы 3

Основная функция виртуального окна просмотра - отслеживать события прокрутки и уведомлять вас, какие элементы в настоящее время отображаются на экране. Используя эту информацию, вы можете изменить источник данных дерева так, чтобы это были только узлы, отображаемые на экране.

Проблема в том, что прямо сейчас область просмотра действительно хорошо работает только с элементами постоянной высоты. Когда вы расширяете узел дерева, этот узел имеет высоту, несовместимую с остальными закрытыми узлами. Чтобы обойти это, вы можете добавить дочерние узлы в источник данных виртуального окна просмотра всякий раз, когда узел расширяется.

На данный момент я проигнорирую проблему с расширенным узлом.

Чтобы получить базовую виртуальную прокрутку с деревом, добавьте это в свой шаблон:

<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/…

androidGenX 10.05.2019 14:42

Небольшая проблема с этим подходом: renderedRangeStream работает вне зоны Angular, поэтому у вас могут возникнуть проблемы с обнаружением изменений на отрисованных узлах дерева. Вы можете решить эту проблему, внедрив CdkVirtualForOf в качестве дочернего представления и подписавшись вместо этого на его наблюдаемый объект viewChange.

Jon Rimmer 31.07.2019 16:54

Одна проблема, которую я вижу в этом подходе, заключается в том, что дерево матов может быть рекурсивным, в то время как этот метод просто сокращает длину корневых элементов. если на втором уровне много элементов, такой подход вообще не поможет с прокруткой.

Mr.Manhattan 16.08.2019 13:29
  • npm install @angular/[email protected] или ng add @angular/[email protected]
  • Импортируйте модуль прокрутки в ваше приложение app.module.ts
    • import { ScrollingModule } from '@angular/cdk/scrolling';
    • добавить ScrollingModule в импорт внутри @ngmodule
  • добавьте свой cdk-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>

Jack 07.06.2020 12:50

Наконец я нашел решение. Оно работает! Пришло время реализовать детали из обычного дерева, которое имеет большой функционал, так что, возможно, возникнут какие-то неприятности.

greygreg87 29.07.2020 14:46

Другие вопросы по теме