angular: después de que ChangeDetectionStrategy.OnPush, la interfaz de usuario habilitada no se actualiza

CorePress2023-11-30  1

Según cambio de traducción:

     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
        });
      }

Espero que esto se deba a un problema de inmutabilidad aquí. es decir, este.menú lateral. ¿Podrías darme alguna pista aquí?

setSideMenu(sideMenu: SideMenuModel): void {

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

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

      },
]

He habilitado changeDetection: ChangeDetectionStrategy.OnPush. Después de eso, la interfaz de usuario no se actualiza correctamente.

Nota: He eliminado el código de plantilla no deseado aquí.

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


------------------------

Con la estrategia OnPush, debe indicarle a su componente que actualice el evento externo/@Input(), como la suscripción observable:

     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
        });
      }
7
  • Sí, ahora funciona. ¿Podría dar más información sobre este caso de uso? ¿Cuál es mejor? es decir, ¿debería utilizar el comportamiento predeterminado sin OnPush o utilizar su método con OnPush? Este es un componente del menú lateral. ¿Cuál tiene mejor rendimiento para la aplicación? - Sampath 6 de junio de 2020 a las 22:24
  • ¿Esto no se debe al problema de mutabilidad en this.sideMenu? - Sampath 6 de junio de 2020 a las 22:28
  • En absoluto, con OnPush, sideMenu debería ser una referencia diferente, como lo hizo: this.sideMenu = .... No funcionará si muta el estado de sideMenu como: this.sideMenu.push (...). Debería haber muchos blogs que hablen sobre cómo funciona OnPush. No creo poder explicarlo mejor. OnPush tendrá un mejor rendimiento porque el cambio de detección se ejecutará con menos frecuencia, la compensación es que necesitará escribir más código y es posible que lo olvide: siempre debe usar la inmutabilidad para la propiedad y usar Cha.ngeDetectorRef.markForCheck() con Observable -HTN 7 de junio de 2020 a las 6:09
  • Como mencioné, este es un problema con la mutación de datos. Entonces he usado BehaviorSubject con tubería asíncrona. Ahora funciona bien sin ningún truco. Su solución está bien si uso una biblioteca de terceros como la API de Javascript de mapas de Google, etc. Pero mi caso de uso es el de trabajo en la Zona Angular. es decir, no es necesario ChangeDetectorRef. Gracias también por tus comentarios. - Sampath 7 de junio de 2020 en13:14
  • Llamar a markForCheck() no es un truco. El uso de BehaviorSubject con async Pipe hace que su código sea aún más complejo, async Pipe simplemente llama a markForCheck() subyacente. Incluso lo considero malo porque ahora tienes dos fuentes para el valor del menú lateral... -HTN 7 de junio de 2020 a las 13:35


------------------------

Como mencioné en mi pregunta, este es un problemah mutación de datos. Entonces he usado BehaviorSubject con tubería asíncrona. Ahora funciona bien sin ningún truco.

Excelente artículo sobre eso: 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);
  }
Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare