angular父子组件之间的传值
父子组件的传值,是mvvm框架中必然绕不过去的话题,下面列举在angular中父子组件传值的各种方式。
一、通过输入型绑定把数据从父组件传到子组件
即带有@Input装饰器,如下面两种方式:
@[Input](https://angular.cn/api/core/Input)() hero: Hero;
@[Input](https://angular.cn/api/core/Input)('master') masterName: string;
父组件在引用子组件的标签的时候,通过 [ ] 符号将父组件的变量名赋值给该变量;
<app-hero-child *[ngFor](https://angular.cn/api/common/NgForOf)="let hero of heroes" [hero]="hero [master]="master"></app-hero-child>
子组件通过在变量名前面加上@Input装饰器的方式,可以从父组件取值,实现父子组件的传值。
二、通过setter截听输入属性值的变化
在第一种方案的基础上,使用一个输入属性setter,以拦截父组件中值的变化,并采取行动。
export class NameChildComponent {
private _name = '';
@[Input]()
set name(name: string) {
this._name = (name && name.trim()) || '<no
name set>';
}
get name(): string { return this._name; }
}
三、通过ngOnChanges()来截听输入属性值的变化
通过OnChanges生命周期钩子接口的ngOnChanges()方法来检测输入属性值的变化并做出回应。
四、父组件监听子组件的事件
子组件暴露一个EventEmitter属性,当事件发生时,子组件利用该属性emits(向上弹射)事件,父组件绑定这个事件属性,并在事件发生时做出回应。
子组件的EventEmitter属性是一个输入属性,通常带有@Output装饰器。
子组件:
// template
<button (click)="vote(false)" [disabled]="didVote">Disagree</button>
// component
@Output() voted = new EventEmitter<boolean>();
vote(agreed: boolean) {
this.voted.emit(agreed);
}
父组件绑定一个事件处理器,用来响应子组件的事件。弹射出的事件,直接写在父组件引入子组件的位置上。
<app-voter (voted)="onVoted($event)"></app-voter>
五、父子组件通过本地变量互动
父组件不能使用数据绑定来读取子组件的属性或者调用子组件的方法。但可以在父组件模板里,新建一个本地变量来代表子组件,然后利用这个变量来读取子组件的属性和调用子组件的方法。
//父组件的template
<button (click)="timer.start()">Start</button>
<button (click)="timer.stop()">Stop</button>
<div class="seconds">{{timer.seconds}}</div>
<app-countdown-timer #timer></app-countdown-timer>
本地变量的写法是(# + 变量名)
在父组件中,把本地变量(#timer)放到子组件标签(<countdown-timer>)中,用来代表子组件,该父组件模板就得到子组件的引用,可以在父组件模板访问子组件的属性和方法。
六、父组件调用@ViewChild()
上面那种本地变量的方式,有局限性,只能在父组件的模板中使用。如果在父组件的类中读取子组件的属性方法,就不能使用本地变量了。
当父组件类需要这种访问时,可以把子组件作为ViewChild,注入到父组件中。
@ViewChild(CountdownTimerComponent)
private timerComponent: CountdownTimerComponent;
首先,你必须导入对装饰器ViewChild
以及生命周期钩子 AfterViewInit
的引用。
接着,通过 ViewChild
属性装饰器,将子组件 CountdownTimerComponent
注入到私有属性 timerComponent
里面。
ngAfterViewInit()
生命周期钩子是非常重要的一步。被注入的计时器组件只有在 Angular 显示了父组件视图之后才能访问.所以需要加上setTimeout()来等下一轮。
ngAfterViewInit() {
setTimeout(() => this.seconds = () =>
this.timerComponent.seconds, 0);
}
七、通过服务来通讯
不会!rxjs看不懂!!!
不过可以通过redux存在统一的store树里面,增删改查都从这里取,变相实现传值。