[英]Angular Change Detection is not triggered with nested ngFor
我目前正在開發一個帶有 NgRx 存儲的更大的 Angular 項目。 該應用程序包含一個無限滾動列表,當到達末尾時會顯示一些骨架項目,當請求完成時,這些骨架項目會被真實項目下推。
在一個組件中,我們需要一個分組/嵌套列表,這會導致嵌套*ngFor
。 由於建議使用 NgRx,因此該組件使用ChangeDetectionStrategy.OnPush
。
現在,當從后端加載列表值時,即使請求已經完成很長時間,列表也需要很長時間才能更新(有時只有在瀏覽器內單擊時才會更新)。 我的第一個猜測是變更檢測存在問題。
這是我的組件目前的樣子的摘錄:
<ul cdkScrollable #groupList>
<li *ngFor="let dayGroup of groupsWithSkeleton$ | ngrxPush | keyvalue: asIsOrder;
let i = index;
trackBy: trackByKey">
<div>{{ dayGroup.key | date }}</div>
<ul>
<li *ngFor="let subGroup of dayGroup.value | keyvalue: asIsOrder;
let i = index;
trackBy: trackByKey">
<!-- stuff -->
</li>
</ul>
</li>
</ul>
private groups$: Observable<Groups> = this.store.select(
Selectors.selectGroups
);
constructor(readonly store: Store<AppState>) {
this.groupsWithSkeleton$ = combineLatest([
this.groups$,
this.isLoadingOrHasMoreItemsAvailable$
]).pipe(
map(([groups, isLoadingOrHasMoreItemsAvailable]) => {
const skeleton: Groups = isLoadingOrHasMoreItemsAvailable ? this.skeletonMap : new Map();
return new Map([...groups, ...skeleton]);
})
);
// [...] more assignments
}
我已經找到了一個可行的解決方案,但我認為它相當難看,我真的不明白為什么這首先不起作用。 (它仍然不是非常快但可以接受。)
解決方案是在創建帶有骨架項目的組后添加它:
tap(() => {
changeDetectorRef.markForCheck();
changeDetectorRef.detectChanges();
})
我還用 MWE 創建了一個 StackBlitz: https://stackblitz.com/edit/angular-ivy-7ycaxv?file=src/app/app.component.ts
也許有人可以幫助我找到潛在的問題和更好的解決方案。
這是一個棘手的問題,文檔實際上並沒有明確說明:
我們可以在滾動調度器的代碼源中找到關於scrolled
的:
為了避免對每個滾動事件進行更改檢測,從此 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 發出的所有事件都將在 Angular 區域之外運行。 如果由於滾動事件而需要更新任何數據綁定,則必須 * 使用 `NgZone.run 運行回調
這就是為什么您需要顯式調用會觸發 CD 的東西的原因。 在您的情況下, changeDetectorRef.detectChanges()
就足夠了!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.