我有以下模板
<div *ngIf="hotels$ | async as hotels; else loadGif ">
<div *ngFor="let hotel of hotels | hotelsFilter: _filteredType; first as f; index as i "
appInit [hotel]="hotel " [first]="f ">
<app-card appHighlight [hotel]=hotel></app-card>
</div>
</div>
并且 appInit 指令是为了在列表被过滤后识别酒店列表的第一个元素而编写的。这是 appInit 指令的 ngInit 方法:
constructor(
private __hotelsService: HotelsService
) { }
@Input()
public hotel: Hotel;
@Input()
public first: boolean;
public ngOnInit(): void {
if (this.first) {
this.__hotelsService.selectedHotel$.next(this.hotel);
console.log('first init ' + this.hotel.name);
}else{
console.log('not first init ' + this.hotel.name);
}
}
问题在于,每次过滤和重新呈现酒店列表时ngOnInit
都不会调用指令的方法。问题是为什么以及何时真的应该调用ngOnInit?
每次运行更改检测并更新具有绑定到它们的值的输入时,都会调用ngOnChanges
。ngOnInit
在调用ngOnChanges
后第一次调用。
有关更多详细信息,请参阅 https://angular.io/guide/lifecycle-hooks
当*ngFor
呈现元素时,它会识别值何时相同并重用呈现的项目。 这就是为什么在筛选器更改后不调用在筛选器更改之前呈现的项目的ngOnInit
的原因。
您可以改用每次更新输入时都会调用的ngOnChanges
,或者您可以使输入getter
_first: boolean,
@Input()
public set first(value: boolean) {
this._first = value;
if (this.first) {
this.__hotelsService.selectedHotel$.next(this.hotel);
console.log('first init ' + this.hotel.name);
}else{
console.log('not first init ' + this.hotel.name);
}
}
public get first() : boolean {
return this._first;
}
ngOnInit只会在组件初始化时被调用一次。根据您的需要,您应该使用ngOnChanges在输入属性更改时调用它。
有关生命周期挂钩的更多信息:https://angular.io/guide/lifecycle-hooks