Как построить лениво загружаемую боковую панель в Angular? - PullRequest
0 голосов
/ 04 ноября 2019

В моем Angular App встроен компонент, который обрабатывает информацию о клиентах;это мой ClientDetailsComponent, внутри этого компонента есть другие подкомпоненты, каждый из которых извлекает свои собственные данные, когда пользователь входит в основной ClientDetailsComponent;это, конечно, приводит к тому, что основной компонент загружает много вещей, которые в данный момент могут даже не понадобиться пользователям, поэтому я пытался найти способ ленивой загрузки этих разделов.

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

ClientDetailsCompnent

<div class="wrapper">
    <div class="sidebar-nav">
        <nav>
            <ul class="sections-list" btnRadioGroup [formControl]="navControl">
                <li btnRadio="0" tabindex="0" role="button">Basic Information</li>
                <li btnRadio="1" tabindex="0" role="button" *ngIf="!isNew">PPC Accounts</li>
                <li btnRadio="2" tabindex="0" role="button" *ngIf="!isNew">Campaign Groups</li>
                <li btnRadio="4" tabindex="0" role="button" *ngIf="!isNew">Optimizations</li>
                <li btnRadio="5" tabindex="0" role="button" *ngIf="!isNew">Branding</li>
                <li btnRadio="3" tabindex="0" role="button" *ngIf="!isNew">Sharing</li>
            </ul>
        </nav>
    </div>
    <div class="content">
        <div class="wsm-container">

            <!-- Basic Information -->
            <section id="basic-info" class="wsm-card mx-auto d-none" [ngClass]="navControl.value === '0' ? 'd-flex' : 'd-none'">
            </section>

            <!-- PPC Accounts -->
            <section *ngIf="!isNew" id="ppc-accounts" class="wsm-card mt-4 d-none" [ngClass]="navControl.value === '1' ? 'd-flex' : 'd-none'">
            </section>

            <!-- Campaign Groups -->
            <section *ngIf="!isNew && navControl.value === '2'" class="wsm-card mt-4 d-none" [ngClass]="navControl.value === '2' ? 'd-flex' : 'd-none'">
                <app-campaign-groups [clientID]="param"></app-campaign-groups>
            </section>

            <!-- Optimizer History -->
            <section *ngIf="!isNew && navControl.value === '4'" id="optHistory" class="wsm-card mt-4 d-none" [ngClass]="navControl.value === '4' ? 'd-flex' : 'd-none'">
                <app-optimization-history></app-optimization-history>
            </section>

            <!-- Branding -->
            <section id="brnading" class="wsm-card mx-auto d-none" [ngClass]="navControl.value === '5' ? 'd-flex' : 'd-none'">
            </section>
        </div>
    </div>
</div>

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

Таким образом, один из обходных путей, который я нашел, пробуя различные варианты, заключался в использовании условия navControl.value === '' в директиве *ngIf раздела, поэтому вместо изменения классов только с помощью директивы [ngClass] я также предотвращаюраздел, который будет добавлен в DOM, и фактически я вижу, что запрос для каждого подкомпонента выполняется только после того, как я нажимаю на нужную вкладку.

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

Есть ли способсохранить подкомпонент загруженным после того, как я получу к нему доступ, чтобы он не нуждался в повторной визуализации и повторном получении данных?

1 Ответ

2 голосов
/ 06 ноября 2019

Создать сервис с ReplaySubject:

@Injectable({
  providedIn: "root"
})
export class DataService {
  private _replay: ReplaySubject<any>;
  get replay() {
    if (!this._replay) {
      this._replay = new ReplaySubject();
      this.fakeFetch().then(data => this.replay.next(data));
    }
    return this._replay;
  }

  async fakeFetch() {
    console.log("fakeFetch");
    await new Promise(c => setTimeout(() => c(), 10));
    return { name: "world" };
  }
}

И в вашем компоненте подписаться на тему воспроизведения:

export class HelloComponent {
  name: string;
  constructor(private api: DataService) {
    console.log('render HelloComponent')
    this.api.replay.subscribe(data => {
      this.name = data.name;
    });
  }
}

stackblitz

...