Angular12子组件@Input()在ngAfterViewInit中为undefined问题解决
问题原因及解决办法
原因分析
- 父组件的API请求是异步操作,
ngOnInit中的异步任务完成时间晚于子组件ngAfterViewInit钩子的执行时机。当子组件执行ngAfterViewInit时,父组件还未完成API数据的获取与过滤,因此@Input()绑定的dataSourceInput还未被赋值,输出结果为undefined。 - Angular Material Table能正常渲染是因为其内部实现了输入属性的变化监听,当父组件后续拿到数据并更新
dataSourceInput时,Table会自动响应变化重新渲染,但ngAfterViewInit仅执行一次,无法捕获后续的数据更新。
解决办法
方法1:使用ngOnChanges钩子监听输入变化
子组件中实现ngOnChanges钩子,每次dataSourceInput更新时触发后续处理逻辑:
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; @Component({ selector: 'app-child-table', templateUrl: './child-table.component.html', styleUrls: ['./child-table.component.css'] }) export class ChildTableComponent implements OnChanges { @Input() dataSourceInput: any[]; ngOnChanges(changes: SimpleChanges): void { if (changes.dataSourceInput && changes.dataSourceInput.currentValue) { // 在这里执行数据后续处理 console.log(changes.dataSourceInput.currentValue); } } }
方法2:给输入属性添加setter
通过setter实时监听dataSourceInput的变化,一旦传入有效值就执行处理:
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-child-table', templateUrl: './child-table.component.html', styleUrls: ['./child-table.component.css'] }) export class ChildTableComponent { private _dataSourceInput: any[]; @Input() set dataSourceInput(value: any[]) { this._dataSourceInput = value; if (value) { // 执行后续处理逻辑 console.log(value); } } get dataSourceInput(): any[] { return this._dataSourceInput; } }
方法3:结合async管道优化父组件传递逻辑
父组件将API返回的Observable直接通过async管道绑定到子组件输入,确保数据就绪后再传递:
// 父组件代码 import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { ApiService } from './api.service'; import { filter } from 'rxjs/operators'; @Component({ selector: 'app-parent', template: ` <app-child-table [dataSourceInput]="filteredData$ | async"></app-child-table> ` }) export class ParentComponent implements OnInit { filteredData$: Observable<any[]>; constructor(private apiService: ApiService) {} ngOnInit(): void { this.filteredData$ = this.apiService.getData().pipe( // 这里添加你的数据过滤逻辑 filter(data => data.length > 0) ); } }
此时子组件的ngAfterViewInit可以直接获取到有效值:
// 子组件代码 import { Component, Input, AfterViewInit } from '@angular/core'; @Component({ selector: 'app-child-table', templateUrl: './child-table.component.html', styleUrls: ['./child-table.component.css'] }) export class ChildTableComponent implements AfterViewInit { @Input() dataSourceInput: any[]; ngAfterViewInit(): void { console.log(this.dataSourceInput); // 此时数据已就绪 // 执行后续处理 } }
内容的提问来源于stack exchange,提问作者Isac Freire Bezerra
相关产品推荐
相关产品推荐

