ChangeDetectionStrategy.OnPush 启用后 UI 不更新

After ChangeDetectionStrategy.OnPush enabled UI doesn't update

根据翻译变化:

     setTranslation(): void {
        this.translateService.stream(['Client.Dashboard', 'Client.Active-
Orders']).subscribe(res => {

          const sideMenu: SideMenuModel = {
            dashboard: res['Client.Dashboard'],
            activeOrders: res['Client.Active-Orders'],

          };

          this.setSideMenu(sideMenu); // here it calls
        });
      }

我希望这是由于不可变性问题造成的。即 this.sideMenu。你能给我一些提示吗?

setSideMenu(sideMenu: SideMenuModel): void {

    this.sideMenu = [
      {
        title: sideMenu.dashboard,
        url: '/dashboard',

      },
      {
        title: sideMenu.activeOrders,
        url: '/active-orders',

      },
]

我启用了changeDetection: ChangeDetectionStrategy.OnPush,。在那之后,UI 没有正确更新。

注意:我已经删除了这里不需要的模板代码。

 <ion-menu-toggle auto-hide="false" *ngFor="let s of sideMenu; let i = index">

    <ion-item (click)="selectedIndex = i" routerDirection="root" [routerLink]="[s.url]">

    </ion-item>

  </ion-menu-toggle>

使用 OnPush 策略,您需要告诉您的组件更新外部事件/@Input(),例如可观察订阅:

     constructor(private readonly cdRef: ChangeDetectorRef) {}
     setTranslation(): void {
        this.translateService.stream(['Client.Dashboard', 'Client.Active-
Orders']).subscribe(res => {

          const sideMenu: SideMenuModel = {
            dashboard: res['Client.Dashboard'],
            activeOrders: res['Client.Active-Orders'],

          };

          this.setSideMenu(sideMenu); // here it calls
          this.cdRef.markForCheck(); // Tell Angular to run detectChanges on this component
        });
      }

正如我在问题中提到的,这是数据突变的问题。所以我使用 BehaviorSubjectasync 管道。现在它工作正常,没有任何黑客攻击。

很棒的文章:https://blog.angular-university.io/onpush-change-detection-how-it-works/

html

<ion-menu-toggle *ngFor="let s of sideMenuChanged$ |async; let i = index">


  </ion-menu-toggle>

.ts

  private sideMenuSubject$: BehaviorSubject<any> = new BehaviorSubject<any>(null);
  sideMenuChanged$: Observable<any> = this.sideMenuSubject$.asObservable();

  constructor(private translateService: TranslateService, ) { }

ngOnInit(): void {
  this.setTranslation();
}

 setTranslation(): void {
    this.translateService.stream(['Client.Dashboard', 'Client.Active-Orders']).subscribe(res => {

      const sideMenu: SideMenuModel = {
        dashboard: res['Client.Dashboard'],
        activeOrders: res['Client.Active-Orders'],
       };

      this.setSideMenu(sideMenu);
    });
  }

setSideMenu(sideMenu: SideMenuModel): void {

    this.sideMenu = [
      {
        title: sideMenu.dashboard,
        url: '/dashboard',
        src: '../assets/images/client/dashboard-side-menu.png'
      },
      {
        title: sideMenu.activeOrders,
        url: '/active-orders',
        src: '../assets/images/common/active-orders.png',
        isActiveOrder: true
      },
     ];

    this.sideMenuSubject$.next(this.sideMenu);
  }