删除线格式
当子组件的数据是由父组件通过API获取的时候,容易出现 页面没有渲染数据,那是因为页面渲染的时候虽然请求已经发出但是还没有拿到数据
解决的办法有三种
- *ngIf
- ngOnChanges
- RxJs BehaviorSubject
先来看看代码
parent
.html
<app-child [data]="datafromAPI"></app-child>
.ts
export class AppComponent implements OnInit {
parent = 'This is parent';
datafromAPI: Skill[];
constructor(private _http: HttpClient) { }
ngOnInit() {
this.getDataInParent()
.subscribe(x => {
this.datafromAPI = x;
console.log(this.datafromAPI);
});
}
getDataInParent(): Observable<any> {
return this._http.get('../assets/mock-data/skill.json');
}
}
child
.html
<ul>
<li *ngFor="let s of data">
{{ s.title }}
</li>
</ul>
.ts
@Input()
data: Skill[];
看上去应该是这个样子的,但是—》child组件并没有拿到要显示的数据
- 在父组件html 加上 *ngIf 就可以轻松解决
<div *ngIf="datafromAPI">
<app-post [data]="datafromAPI"></app-post>
</div>
- 有时候子组件拿到数据是要进行一些处理,与父组件的*ngIf 一起在子组件中配套使用ngOnInit也是不能正确的显示数据,因为ngOnInit在生命周期只会加载一次。 为了检测动态的数据变化引入ngOnChanges,在子组件使用生命周期ngOnChanges, 此时,父组件的 *ngIf不再使用
ngOnChanges(changes: SimpleChanges) {
// only run when property "data" changed
if (changes['data']) {
this.groupSkills= this.groupByCategory(this.data);
}
}
- 使用ngOnChanges可以时时检测数据的变化,但是SimpleChanges的changes只接受string类型,如果要检测其它类型,还需要做很多的工作,此时引入RxJs BehaviorSubject
private _data = new BehaviorSubject<Skill[]>([]);
@Input()
set data(value) {
// set the latest value for _data BehaviorSubject
this._data.next(value);
};
get data() {
// get the latest value from _data BehaviorSubject
return this._data.getValue();
}
groupSkills: GroupSkills[];
constructor() { }
ngOnInit(): void {
this._data
// unsubscribe once groupPosts has value
.subscribe(x => {
this.groupSkills = this.groupByCategory(this.data);
});
}