我有一個父母通過訂閱一個可觀察的資料從資料庫中獲取資料。
我的問題是我有一個子組件在其 ngOnInit 方法中使用來自父組件的資料。這會產生一個錯誤,因為在渲染子組件時資料還不存在。
在下文中,我收到錯誤,因為我從可觀察到的“學科”尚未回傳。但是孩子被渲染了,此時 ngOnInit 正在訪問一個空陣列。
如果我用一個值對學科進行硬編碼而不是等待可觀察物件回傳資料,這很好用。
所以問題是,在子組件的 ngOnInit 訪問它之前,如何確保資料在我的變數中。
在 Parent 我在 ngOnInit 方法中有這個:
this.disciplines = [];
let getOptions = this.service.getOptions().subscribe((data: any) => {
this.populateOptions(data);
});
...
populateOptions(data: any): void {
this.disciplines = data['disciplines'];
}
在父母模板中
<cmp-child
[disciplines]="disciplines"
</cmp-child>
在子組件的ngOnInit中,
ngOnInit(): void {
this.populateOptions()
}
populateOptions(): void {
this.advanced = this.disciplines.filter(d => d.isAdvancedDiscipline === true).map(m => m.id);
console.log("disciplines: ", this.disciplines);
}
謝謝,
湯姆
uj5u.com熱心網友回復:
您可以更改父模板以僅在discipline具有值的情況下呈現子組件:
<cmp-child *ngIf="disciplines"
[disciplines]="disciplines"
</cmp-child>
這樣,您的子組件僅在discipline具有值時才被實體化和初始化。這也意味著當discipline設定回 null 或 undefined時,您的子組件會被銷毀。
uj5u.com熱心網友回復:
而不是依賴ngOnInit生命周期鉤子,你應該在ngOnChanges鉤子中做出反應
public ngOnChanges(changes: SimpleChanges): void {
const disciplinesChanged = 'disciplines' in changes;
if(disciplinesChanged){
this.populateOptions()
}
}
uj5u.com熱心網友回復:
使用 NgOnChange。
ngOnChanges(changes: SimpleChanges) {
if(changes.disciplines && changes.disciplines.currentValue) {
this.reports = changes.disciplines.currentValue;
}
populateOptions(): void {
this.advanced = this.disciplines.filter(d => d.isAdvancedDiscipline ===
true).map(m => m.id);
console.log("disciplines: ", this.disciplines);
}
在您的 NgOnInit 中,您還可以進行 if 檢查以避免在未定義時運行代碼的問題。
if(this.disciplines)
//call populate
這樣做的方式是,首先您的代碼將嘗試執行其OnInit方法中可用的內容,因為您注意到結果可能仍未定義。該OnChange然而,一旦底層輸入資料已更改將被再次觸發。
另一種可能的方法是在父組件中顯示某種加載指示器。您可以使用帶有 reducer 等的完整的 store 實作來實作這一點,或者只是在父組件中執行此操作。
在您的 parent.ts 檔案中:
//By convention observables have a $ appended at the end of their variable name
loading$ = new BehaviorSubject(true)
disciplines$ = new BehaviorSubject(YourDisiciplineObject[]);
OnInit() {
let getOptions = this.service.getOptions().subscribe((data: any) => {
loading$.next(false); //finished loading
this.populateOptions(data);
});
}
populateOptions(data: any): void {
disciplines$.next(data['disciplines')
this.disciplines = data['disciplines'];
}
然后,您可以在前端使用角度異步管道(這里我們添加了一個布爾型別的加載輸入)
<cmp-child
[loading] = "(loading$ | async)"
[disciplines]="(disciplines$ | async)"
</cmp-child>
異步管道的美妙之處在于,一旦回傳一些資料或沒有資料,它實際上會正常更新結果,具體取決于 API 呼叫的最終結果。最好在使用 redux 模式時配對(在我看來),但它確實為您處理了 observable。無需訂閱它或類似的東西。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/409357.html
標籤:
