Angular: cdkVirtualFor 不渲染新项目
Angular: cdkVirtualFor not rendering new items
我正在构建一个垂直滚动的日历。我正在加载最初的日子,但是当新的日子被添加到列表中时,它们并没有被渲染。
<cdk-virtual-scroll-viewport
class="demo-viewport"
[itemSize]="100"
(onContentScrolled)="handleScrollChange($event)"
>
<calendar-day
*cdkVirtualFor="let day of days; trackBy: trackByFn"
[day]="day"
></calendar-day>
</cdk-virtual-scroll-viewport>
<button (click)="goToToday()">go</button>
我有一个 BehaviorSubject
更新日期的服务。我知道天数列表正在更新,但似乎没有检测到更改。
ngOnInit() {
this._daysService.days$.subscribe(days => {
this.days = days;
})
this.watchScroll();
this.handleScrollingUp();
this.handleScrollingDown();
}
有关详细信息,StackBlitz 存储库是 public https://stackblitz.com/edit/material-infinite-calendar
可以这样做:
您可以初始化另一个变量作为您的行为主体的观察值 "days$"。
日历-days.service.ts
public days$: BehaviorSubject<Date[]>;
public dayObs$: Observable<Date[]>
constructor() {
this.days$ = new BehaviorSubject<Date[]>(this._initialDays);
this.dayObs$ = this.days$.asObservable();
}
然后像这样在 ngOnInit 中订阅 calender.component.ts 中的可观察对象:
this._daysService.dayObs$.subscribe(days => {
this.days = days;
})
*cdkVirtualFor
只会在您不可变地更新它时才会更新,即您无法在初始化后更新数组。我们使用传播运算符来获取您要查找的内容。
检查这个非常简单stackblitz...这里我使用了两种方法,你可以试试看:
addCountryOld
方法通过将对象推送到我们的数组来改变数组,因此渲染的视图不会更新。
addCountryNew
方法通过展开运算符使用不变性,从而导致渲染视图得到更新。
这是 addCountryNew 的代码:
addCountryNew(){
let newObj = {'name':'stack overflow country', "code":'SO'};
this.myList = [...this.myList, newObj];
}
而不是
this.days = days;
做
this.days = [...days];
我想通了。
最初,我是通过像这样获取当前值来添加新的天数
let items = this.items$.value;
items.push(newItem);
this.items$.next(items)
显然,这实际上是 BehaviorSubject
值的突变,因此不会为 return 创建新数组,也不会触发更改检测。
我改成了
let items = [...this.items$.value];
items.push(newItem);
this.items$.next(items)
一切都很好。
所以,虽然这里的答案是正确的,因为我正在改变原始数组,但我需要的信息是 调用 next()
和 BehaviorSubject
的当前版本value 不会发出 new 数组。 emit
事件不保证不变性。
我对 *cdkVirtualFor
有一个奇怪的行为,即使我按照上面大多数答案中的描述不可变地设置变量,它也不会更新。
在我的场景中,如果从空数组更新为 non-empty 数组时不会呈现项目。
花了很多时间后,我最后一次恢复是根据项目的存在用 ng-container
包装 cdk-virtual-scroll-viewport
。
<ng-container *ngIf="items.length">
<cdk-virtual-scroll-viewport>
<div *cdkVirtualFor="let item of items">
...
</div>
</cdk-virtual-scroll-viewport>
</ng-container>
这样,当物品可用时,整个容器都是 re-initialized。这解决了我的问题。
我正在构建一个垂直滚动的日历。我正在加载最初的日子,但是当新的日子被添加到列表中时,它们并没有被渲染。
<cdk-virtual-scroll-viewport
class="demo-viewport"
[itemSize]="100"
(onContentScrolled)="handleScrollChange($event)"
>
<calendar-day
*cdkVirtualFor="let day of days; trackBy: trackByFn"
[day]="day"
></calendar-day>
</cdk-virtual-scroll-viewport>
<button (click)="goToToday()">go</button>
我有一个 BehaviorSubject
更新日期的服务。我知道天数列表正在更新,但似乎没有检测到更改。
ngOnInit() {
this._daysService.days$.subscribe(days => {
this.days = days;
})
this.watchScroll();
this.handleScrollingUp();
this.handleScrollingDown();
}
有关详细信息,StackBlitz 存储库是 public https://stackblitz.com/edit/material-infinite-calendar
可以这样做:
您可以初始化另一个变量作为您的行为主体的观察值 "days$"。
日历-days.service.ts
public days$: BehaviorSubject<Date[]>;
public dayObs$: Observable<Date[]>
constructor() {
this.days$ = new BehaviorSubject<Date[]>(this._initialDays);
this.dayObs$ = this.days$.asObservable();
}
然后像这样在 ngOnInit 中订阅 calender.component.ts 中的可观察对象:
this._daysService.dayObs$.subscribe(days => {
this.days = days;
})
*cdkVirtualFor
只会在您不可变地更新它时才会更新,即您无法在初始化后更新数组。我们使用传播运算符来获取您要查找的内容。
检查这个非常简单stackblitz...这里我使用了两种方法,你可以试试看:
addCountryOld
方法通过将对象推送到我们的数组来改变数组,因此渲染的视图不会更新。addCountryNew
方法通过展开运算符使用不变性,从而导致渲染视图得到更新。
这是 addCountryNew 的代码:
addCountryNew(){
let newObj = {'name':'stack overflow country', "code":'SO'};
this.myList = [...this.myList, newObj];
}
而不是
this.days = days;
做
this.days = [...days];
我想通了。
最初,我是通过像这样获取当前值来添加新的天数
let items = this.items$.value;
items.push(newItem);
this.items$.next(items)
显然,这实际上是 BehaviorSubject
值的突变,因此不会为 return 创建新数组,也不会触发更改检测。
我改成了
let items = [...this.items$.value];
items.push(newItem);
this.items$.next(items)
一切都很好。
所以,虽然这里的答案是正确的,因为我正在改变原始数组,但我需要的信息是 调用 next()
和 BehaviorSubject
的当前版本value 不会发出 new 数组。 emit
事件不保证不变性。
我对 *cdkVirtualFor
有一个奇怪的行为,即使我按照上面大多数答案中的描述不可变地设置变量,它也不会更新。
在我的场景中,如果从空数组更新为 non-empty 数组时不会呈现项目。
花了很多时间后,我最后一次恢复是根据项目的存在用 ng-container
包装 cdk-virtual-scroll-viewport
。
<ng-container *ngIf="items.length">
<cdk-virtual-scroll-viewport>
<div *cdkVirtualFor="let item of items">
...
</div>
</cdk-virtual-scroll-viewport>
</ng-container>
这样,当物品可用时,整个容器都是 re-initialized。这解决了我的问题。