对于略微接触过Angular组件的同学来说,父子组件传值应该没有什么问题。
本文想谋求的是用一个艰深解释,帮忙同学们了解的更精确。
零、常识铺垫
CSS选择器
在介绍父子组件之前,先要理解一个概念——selector、选择器
咱们定义一个新组件时,肯定会有这个属性:
@Component({ selector: 'app-village-edit', ① templateUrl: './village-edit.component.html', styleUrls: ['./village-edit.component.scss']})
其中①就是选择器,就是通知别的组件,如果想调用我这个组件,就要应用本组件的选择器<selectorName></selectorName>
来调用。
实质上就是定义了组件的HTML标签,就像常见的<p>
标签、<button>
标签一样。
一、什么是父子组件
就像事实中父母和孩子的关系是绝对的一样,一个人对于它的父母来说,就承当了孩子的角色;对于它的孩子来说则承当了父母的角色。
父组件和子组件也是绝对的。
假如,一个组件在本人的HTML模板中,通过选择器(也就是特定的HTML标签)来调用其余组件时。咱们称这个组件为父组件,而那个被调用的组件称为子组件。
二、父组件调用子组件的办法
定义了两个类:
child.component.ts,它的选择器selector是: 'app-child'
parent.component.ts,它的选择器selector是: 'app-parent',
此时,在parent组件的HTMl中援用child组件的选择器:
<app-child></app-child>
这样就实现了子组件的调用。
此时,如果通过路由加载父组件,就会发现子组件也会在特定的地位被渲染进去。
三、父组件向子组件传值
子组件应用@input装璜器接收数据
子组件从父组件接管的值,会保留到子组件的变量中。
所以用来接管传值的变量与一般变量惟一的区别,就是在惯例的变量上减少一个@input()注解。
定义一般变量是这样的:
master = 'Master';
如果用来接管传值,只有改成这样:
@Input() master = 'Master';
这样,master变量默认是'Master'字符串。
但如果父组件向其传值,变量就变成了接管的值。
父组件应用方括号[]发送数据
惯例形式调用子组件:
<app-child></app-child>
如果子组件能够接收数据,就能够用[propertyName] = value的办法来传值。
例如:
<app-child [master]="hero"> </app-child>
用这种写法能够实现:一旦组件渲染实现后,子组件中的master变量就是'hero'的值了。
当父组件中的变量值变动时,子组件也会同步变动,
也就是说,子组件能够监听传过来的值的变动信息。
降级:子组件通过set办法监听传入数据变动
在下面的形式中,对于传过来的值,尽管能够监听变动,但局限在于:子组件只能间接应用传入的值。
如果想对传入的值进行解决或过滤,就要略微调整一下子组件。
惯例状况下,子组件是通过给变量加上@Input装璜器来接管参数的:
@Input() name = 'name';
如果想解决参数,只须要把接管传值的变量变成set办法即可:
@Input() get name(): string { return this._name; }set name(name: string) { // 此处能够减少其余解决逻辑 this._name = name; } private _name = '';
此时,_name
是外部变量,当父组件对于name属性传入值的时候,会主动执行set name办法给_name
赋值并减少其余的解决逻辑。
另一种降级:子组件通过ngOnChanges()生命周期钩子监听传入数据变动
官网文档中写到:“当须要监督多个、交互式输出属性的时候,ngOnChanges()比用属性 setter 办法更适合。”
惯例状况下,子组件是通过给变量加上@Input装璜器来接管参数的:
@Input() param1 = 'string1';@Input() param2 = 'string2';
当咱们要监听多个变量的变动并做出反馈时,能够用ngOnChanges()办法:
@Input() param1 = 'string1';@Input() param2 = 'string2';ngOnChanges(changes: SimpleChanges) { ① for (const propName in changes) { ② // 通过变量名获取变动信息 const changedProp = changes[propName]; // 获取上一个值 const from = JSON.stringify(changedProp.previousValue); ③ // 获取以后值 const to = JSON.stringify(changedProp.currentValue); ④ // 此处能够增加其余处理过程了 ⑤ } }
① 执行ngOnChanges()办法时,能够用一个SimpleChanges参数来取得以后组件所有参数的变动状况。
② 通过循环取得每一个参数的上一个值和以后值。
③ 取得上一个值
④ 取得以后值
⑤ 依据业务逻辑增加其余处理过程
四、子组件向父组件传值
子组件向父组件弹射事件
刚刚讲到了子组件如何获取父组件的传入的变量,如何监听父组件的变动,以及如何解决传入的值。
接下来讲反向的传输:父组件如何监听子组件的变动,并做出反馈。
定义一般变量是这样的:
param1 = 'String1';
如果想把这个变量裸露给父组件,须要在变量前退出@output()装璜器,并且给他赋值一个变量弹射器:
@Output() param1 = new EventEmitter<string>();
此处EventEmitter是变量弹射器,EventEmitter须要一个确定的类型。
但此时,这个param1变量就不能再用等号"="赋值了,如果想让父组件监听到变动,就须要用弹射办法.emit
:
this.param1.emit("String2");
接下来返回父组件。
父组件监听子组件弹射的事件
刚刚曾经在子组件设置好了裸露的变量,那么父组件如何接管呢?
惯例的父组件调用子组件:
<app-child></app-child>
如果想监听子组件的某个变量,能够应用圆括号():
<app-child (param1)="function1($event)"></app-child>
$event 是Angular内置的事件变量。
function1咱们在父组件中定义的解决变动的办法。
应用形式如下:
function1(param2: boolean) { // 这个param2为咱们本人定义的参数名, // 实质上是子组件中变动的param1参数,但不必和子组件中的参数名雷同 // 在此处减少处理过程即可}
此时,当param1的值发生变化,就会执行function1,并且传入一个事件,事件的本质内容就是子组件定义的param1参数。
function1办法把参数作为param2接管,并增加处理过程。
五、总结
- Angular中,在HTML通过selector选择器调用的组件称为子组件。
- 父组件向子组件传值应用方括号[]
- 子组件有两种形式接管值: @input + 变量名、@Input + set办法
- 子组件想父组件传递事件应用EventEmitter
- 父组件接管事件应用圆括号(),并申明一个解决办法用来调用
相熟的格调,一图胜千言:
六、后记
是不是有似曾相识的感觉,在刚开始接触Angular时就晓得,能够应用方括号[]来绑定原生HTML标签的某些属性,例如:
<p [id]="sayHelloId" [style.color]="fontColor"> You can set my color in the component!</p>
另一方面,还有一个相似之处就是,Angular中也是应用圆括号()来绑定原生HTML标签的某个办法,例如:
<button (click)="onClick()"> 点我!</button>
这些是偶合吗?并不是。
咱们能够这样了解:
Angular中所有的原生HTML标签都变成了组件。
之所以很多标签中能够用方括号[]绑定属性、应用圆括号()绑定办法,是因为Angular曾经为咱们扩大了原生的HTML标签,使它们具备了接管和发送数据的能力!
换言之,在Angular外部的组件中,曾经为咱们加上了许许多多的@input和@output装璜器,咱们能力不便的绑定这些属性和办法。