如何通过简单的代码描述Angular父组件、子组件传值
作者:LYX6666
引言
对于稍微接触过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参数来获得当前组件所有参数的变化情况。
② 通过循环获得每一个参数的上一个值和当前值。
③ 获得上一个值④ 获得当前值⑤ 根据业务逻辑添加其他处理过程
注:由于ngOnChanges方法调用非常频繁,会导致性能问题或者软件崩溃,所以建议少用。
四、子组件向父组件传值
子组件向父组件弹射事件
刚刚讲到了子组件如何获取父组件的传入的变量,如何监听父组件的变化,以及如何处理传入的值。
接下来讲反向的传输:父组件如何监听子组件的变化,并做出反应。
定义普通变量是这样的:
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装饰器,我们才能方便的绑定这些属性和方法。
总结
到此这篇关于如何通过简单的代码描述Angular父组件、子组件传值的文章就介绍到这了,更多相关Angular父组件、子组件传值内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!