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
});
}
正如我在问题中提到的,这是数据突变的问题。所以我使用 BehaviorSubject
和 async
管道。现在它工作正常,没有任何黑客攻击。
很棒的文章: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);
}
根据翻译变化:
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
});
}
正如我在问题中提到的,这是数据突变的问题。所以我使用 BehaviorSubject
和 async
管道。现在它工作正常,没有任何黑客攻击。
很棒的文章: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);
}