对于略微接触过 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装璜器,咱们能力不便的绑定这些属性和办法。