typescript 如何优化Angular中的更改检测?

toiithl6  于 2023-06-07  发布在  TypeScript
关注(0)|答案(1)|浏览(148)

我有两个组件和一个服务。我认为问题在于,当我从一个路由组件的视图中点击出不同组件(matMenu和输入字段)的元素时,路由组件似乎会重新呈现自己。如果所述被路由的组件正在生成错误(在这种情况下是GET错误),则这实际上仅成为问题(至少到目前为止)。因此,通过重复相同的操作,控制台可能会充满大量错误。我想了解在这种情况下会发生什么,以及如何进行优化。
组件A使用matMenu,

<nav class="navbar">
      <div class="d-flex justify-content-start align-items-center">
        <a mat-icon-button href="" class="icon-button">
          <mat-icon>home</mat-icon>
        </a>
        <span fxHide.gt-sm>
          <button mat-icon-button class="icon-button" [matMenuTriggerFor]="menu"> 
            <mat-icon>menu</mat-icon>
          </button>
        </span>
        <span fxHide.lt-md>
          <button type="button" class="btn btn-primary" [matMenuTriggerFor]="menu"><b>Alkatrészek</b></button>
          <button type="button" class="btn btn-primary"><b>Szolgáltatások</b></button>
          <button type="button" class="btn btn-primary"><b>Vásárlási információk</b></button>
          <button type="button" class="btn btn-primary"><b>Elérhetőség</b></button>
        </span>
      </div>
      <div>
        <mat-menu #menu="matMenu">
          <button mat-menu-item *ngFor="let item of kategoriaList$ | async"
           (click)="setCategoryPage(item.nev)">{{item.nev}}</button>
        </mat-menu>
        <ng-container *ngIf="alkatreszList$">
          <app-search-bar #searchBar [alkatreszList$]="alkatreszList$"></app-search-bar>
        </ng-container>
      </div>
    </nav>

在哪里

setCategoryPage(category: string) {
    if (category !== this.categoryPageService.getCategory()) {
      this.categoryPageService.setCategory(category);
      this.categoryPageService.setShowCategoryPage(true);
    }
  }

正在调用服务

export class CategoryPageService {
  private showCategoryPageSubject = new BehaviorSubject<boolean>(false);
  showCategoryPage$ = this.showCategoryPageSubject.asObservable();
  category: string = '';

  getCategory(): string {
    return this.category;
  }

  setCategory(categoryIn: string) {
    this.category = categoryIn;
  }

  setShowCategoryPage(showCategoryPage: boolean) {
    this.showCategoryPageSubject.next(showCategoryPage);
  }
  
  constructor() { }
}

然后,从组件A到组件B进行路由

<body>
  <img *ngIf="!(showCategoryPage$ | async)" src="assets\20170822_180636.jpg">
    <app-category-page *ngIf="showCategoryPage$ | async"></app-category-page>
</body>

在组件B中,网格中有一个carousel,其中填充了来自数据库的数据(就像在组件A中一样)

async ngOnInit() {
    this.alkatreszList$ = this.service.getAlkatreszList();
    this.kategoriaList$ = this.service.getKategoriaList();
    this.autoTipusList$ = this.service.getAutoTipusList();
    this.kategoria.push(this.categoryService.getCategory());
    this.kategoria = this.kategoria.map((value: string) => value.trim().replace(/\s+/g, ' '));
    this.searchService.setCategoryFilter(this.kategoria);
    this.filteredAlkatreszek$ = this.searchService.getFilteredAlkatreszek(this.alkatreszList$);
    this.showCategoryPage$ = this.categoryService.showCategoryPage$;
  }

calculateRows(items: any[]): any[][] {
    const maxColumns = 6;
    const numRows = Math.ceil(items.length / maxColumns);
    const rows: any[][] = [];
  
    for (let i = 0; i < numRows; i++) {
      rows.push(items.slice(i * maxColumns, (i + 1) * maxColumns));
    }
  
    return rows;
  }
  
  getRowItems(items: any[], rowIndex: number): any[] {
    const maxColumns = 6;
    const rowItems = items.slice(rowIndex * maxColumns, (rowIndex + 1) * maxColumns);
  
    return rowItems;
  }

在模板中

<ng-container *ngIf="showCategoryPage$ | async">
  <div>
    <p>IT WORKS</p>
  </div>
  <div class="container text-center" *ngIf="(filteredAlkatreszek$ | async) as filteredAlkatreszek">
      <div class="row" *ngFor="let row of calculateRows(filteredAlkatreszek); let i = index;">
          <ng-container>
              <div class="col" *ngFor="let item of getRowItems(filteredAlkatreszek, i)">
                  <div id="imageCarouselCategoryPage" class="carousel slide" data-bs-ride="false">
                      <div *ngIf="item.kepek.split(';').length > 1" class="carousel-indicators">
                        <button type="button" [attr.data-bs-target]="'#imageCarouselCategoryPage'" [attr.data-bs-slide-to]="i" [class.active]="i === 0" *ngFor="let img of item.kepek.split(';');
                        let i = index" [attr.aria-label]="'Slide ' + (i + 1)"></button>
                      </div>
                      <div class="carousel-inner">
                          <div class="carousel-item active" [class.active]="i === 0" *ngFor="let img of item.kepek.split(';'); let i = index">
                              <img class="d-block w-100" [src]="'https://localhost:7094/images/' + img" style="max-height: 100vh; max-width: 100%;">
                              <div class="carousel-caption d-none d-md-block">
                                  <h5>{{item.nev}}</h5>
                                  <p>{{item.ar}}</p>
                              </div>
                          </div>
                      <button class="carousel-control-prev" type="button" data-bs-target="#imageCarouselCategoryPage" data-bs-slide="prev">
                        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
                        <span class="visually-hidden">Previous</span>
                      </button>
                      <button class="carousel-control-next" type="button" data-bs-target="#imageCarouselCategoryPage" data-bs-slide="next">
                        <span class="carousel-control-next-icon" aria-hidden="true"></span>
                        <span class="visually-hidden">Next</span>
                      </button>
                    </div>
                  </div>
                </div>
          </ng-container>
      </div>
  </div>
</ng-container>

我提到的输入字段本身从组件A路由到另一个组件(组件C)。

<ng-container *ngIf="alkatreszList$">
 <app-search-bar #searchBar [alkatreszList$]="alkatreszList$"></app-search-bar>
</ng-container>

那么,为什么当单击组件A /组件C中的元素时,组件B会重新呈现(如果这是发生的情况)?这种行为与变化检测有什么关系?

jbose2ul

jbose2ul1#

Angular的更改检测在事件发生时触发。当更改检测被触发时,Angular会检查组件的模板是否有任何更新,并在必要时应用它们。https://angular.io/api/core/ChangeDetectionStrategy
使用ChangeDetectionStrategy.OnPush或本地化更改检测。
另外,通过使用不可变的数据结构,确保组件A、B和C之间共享的数据是不可变的。
在最新的版本(16)中,Angular 还引入信号https://angular.io/guide/signals,并且在下一版本中引入信号分量。

相关问题