[英]How to access variables other than @Input params on ngOnChanges in Angular?
我遇到了一個場景,我需要對 ngOnchanges 上的數據進行一些處理(因為數據來自父組件的 @Input 數據綁定屬性)。 在此轉換期間,我需要使用在 ngOnInit 中初始化的屬性。 我嘗試直接使用它,但值未定義。 有人可以讓我知道我該如何實現這一目標。 下面是我的場景的示例代碼。
ParentComp HTML
<myParent [data]="list$ | async"></myParent>
ChildComp TS
export class {
@Input() data : any ; //data from parent
breakPoint$: Observable<number>
constructor(){}
ngOnInit(){
this.breakPoint$ = fromEvent(this.window, 'resize').pipe(
map(() => this.numOfCols())
);
}
ngOnChanges(changes: SimpleChanges) {
if (changes['data']) {
// need to do some data processing here based on numOfColumns value, so trying to access
this.breakPoint$.pipe(
) // Here i get cannot read property pipe of undefined error
);
numOfCols(): number {
return this.breakpointObserver.isMatched(`(max-width: 1008px)`) ? 4 : 5;
}
我建議在這里使用withLatestFrom
rxjs 運算符。 我將為numOfColumns
創建一個 Observable ,只要它更新,最終訂閱就會觸發。 但是:它不會觸發,直到您擁有來自ngOnInit()
的數據(第二個 Observable),並且僅在之后更新numOfColumns
時才會觸發,即BreakPoint
的后續更改不會觸發訂閱,如果您希望它是兩者都觸發,然后您可以使用zip代替。
我在setter
中執行此操作,您也可以使用ngOnChanges
_numOfColumns;
numOfColumnsObs$ = new BehaviorSubject(false);
set numOfColumns(val) {
this._numOfColumns = val;
this.numOfColumnsObs$.next(val);
}
get numOfColumns() {
return this._numOfColumns
}
ngOnInit() {
this.breakPoint$ = fromEvent(this.window, 'resize').pipe(
map(() => this.numOfCols())
);
// new code here.
this.numOfColumnsObs$.pipe(withLatestFrom(this.breakPoint$))
.pipe(filter(([columns]) => columns !== false))
.subscribe(([columns, breakPoint]) => {
// do the changes you wanted in `ngOnChanges`;
})
}
你在這里需要一個 BehaviorSubject,因為 observable 會在訂閱之前發出。 因為有一個 BehaviorSubject,所以有一個 hack,我用false
初始化了它。 假設 numOfColumns 永遠不會出現false
。 如果可以,您可以使用任何不可能的值對其進行初始化,然后通過管道對其進行過濾。
您可以添加另一個輸入屬性並將 numOfCols$ 移動到父組件中。
ParentComp HTML
<myParent [data]="list$ | async"
[numOfCols]="numOfCols$ | async>
</myParent>
家長委員會 TS
numOfCols$: Observable<number>;
constructor(private breakpointObserver: BreakpointObserver) {
this.numOfCols$ = breakpointObserver.observe('(max-width: 1008px)').pipe(
map(({matches}) => matches ? 4 : 5)
);
}
ChildComp TS
@Input() data: any;
@Input() numOfCols: number;
ngOnChanges(changes: SimpleChanges) {
if (changes['data']) {
// You can use this.numOfCols here
}
}
ngOnChanges 在 ngOnInit 之前首先觸發。 因為 Inputs 在 ngOnInit 之前填充。
如果您需要來自 ngOnInit 的值,您可以在 ngOnChanges 中使用 boolean "isInitDone"。 並且不要忘記在您的 ngOnInit 中將此 boolean 設置為 true。
但是,您還應該觸發 ngOnChanges 方法中所做的事情。 所以也許把它放在一個方法中,ngOnChanges 和 ngOnInit 都會調用......
另一種解決方案是將 ngOnInit 代碼移動到 ngOnChanges,在if (this.breakpoint$)
內
Angular 的組件生命周期鈎子按以下順序觸發:
如您所見,您正在嘗試訪問未在第一個 ngOnChanges 中定義的屬性。 您可以像這樣在 if 語句中簡單地添加一個檢查:
ngOnChanges(changes: SimpleChanges) {
if (changes['data'] && !!this.breakPoint$) {
....
或者您甚至可以在 ngOnInit 之外定義 breakPoint$,如下所示:
@Input() data : any ; //data from parent
breakPoint$: Observable<number> = fromEvent(this.window, 'resize').pipe(
map(() => this.numOfCols())
);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.