在Angular中,组件可以通过传递数据或事件与另一个组件共享数据和信息。一个组件可以在另一个组件内部使用,从而创建一个组件层次结构。在另一个组件内部使用的组件称为子组件,封闭组件称为父组件。组件可以通过各种方式相互通信,包括:
- 使用 @ Input()
- 使用 @ Output()
- 使用服务
- 父组件调用ViewChild
- 父交互与子使用局部变量
在本文中,我们将重点介绍子组件如何使用 @ Input() 属性与父组件进行交互。我们还将研究拦截输入消息并记录输入消息中的更改。
让我们考虑在下面的清单中创建的组件。我们已经创建了一个名为AppChildComponent的组件,该组件将在另一个组件中使用。
从 “@ angular/core” 导入 { Component};@ 组件 ({选择器: ''appchild',模板: “ < h2 > Hi {{greetMessage}} </h2>”})导出类AppChildComponent {greetMessage: string = "我是孩子"}
我们还创建了另一个名为AppComponent的组件。在AppComponent中,我们使用AppChildComponent:
从 “@ angular/core” 导入 {Component};从 “ ./appchild.com组件” 导入 {AppChildComponent};@ 组件 ({选择器: “ '我的应用程序 ”,模板: '< h1 > Hello {{message}} < /h1> <br/ < appchild >< /appchild> ',})导出类AppComponent { 消息: string = "我是父"}
在上面的清单中,AppComonent使用的是AppChildComponent,因此AppComponent是父组件,而AppChildComponent是子组件。
传递数据从父组件到子组件
让我们从将数据从父组件传递到子组件开始。这可以使用input属性来完成。@ Input装饰器或输入属性用于将数据从父组件传递到子组件。为此,我们需要修改子AppChildComponent,如下所示:
从 “@ angular/core” 导入 { Component,Input,OnInit};@ 组件 ({选择器: ''appchild',模板: “ < h2 > Hi {{greetMessage}} </h2>”})导出类AppChildComponent实现OnInit { @ Input() greetMessage: string; 构造函数 (){}ngOnInit(){}}
正如您所注意到的,我们已经用 @ Input() 修饰符修改了greetMessage属性。此外,我们实现了onInit,稍后将在演示中使用。因此,本质上,在子组件中,我们用 @ Input() 装饰器修饰了greetMessage属性,以便可以从父组件设置greetMessage属性的值。
接下来,让我们修改父组件AppComponent以将数据传递给子组件。
从 “@ angular/core” 导入 {Component};从 “ ./appchild.com组件” 导入 {AppChildComponent};@ 组件 ({选择器: “ '我的应用程序 ”,模板: '< h1 > Hello {{message}} < /h1> <br/ < appchild [greetMessage] = "childmessage" >< /appchild> ',})导出类AppComponent { 消息: string = “我是父”childmessage : string = “ 我从父组件传递到子组件”}
从父组件中,我们设置子组件的属性greetMessage的值。要将值传递给子组件,我们需要在方括号内传递子组件属性,并将其值设置为父组件的任何属性。我们将childmessage属性的值从父组件传递给子组件的greetMessage属性。
截获输入从父组件在子组件
我们可能需要在子组件中拦截从父组件传递的数据。这可以在输入属性上使用getter和setter来完成。
假设我们希望拦截子组件中的传入消息,并将其与一些字符串组合。为此,我们创建了一个名为 _greetmessage的属性,并使用 @ Input() 装饰器为 _greetmessage属性创建getter和setter。在getter中,我们拦截来自父组件的输入并将其与字符串组合。这可以如下所示:
从 “@ angular/core” 导入 { Component,Input,OnInit};@ 组件 ({选择器: ''appchild',模板: '< h2 > Hi {{_ greetMessage}} </h2>'})导出类AppChildComponent实现OnInit {_greetMessage : string; 构造函数 (){}ngOnInit(){} @ Input()设置greetMessage(message : string ){ 这个 ._Greetmessage = “操纵子组件” 消息;}获取greetmessage(){ 这个还回去。_greetMessage;}}
在setter中,我们正在处理来自父组件的传入数据,并在其中附加一些文本。请记住,无论我们是否拦截消息,父组件的行为都不会改变。为了进一步研究它,让我们再举一个例子,创建一个子组件,它将显示从父组件传递的名称。如果父组件传递空名称值,则子组件将显示一些默认名称。为此,我们修改了子组件中的setter。在setter中,我们检查名称值是否被传递。如果未传递或为空字符串,则name的值将分配给默认值。可以创建子组件,如下面的列表所示:
从 “@ angular/core” 导入 { Component,Input,OnInit};@ 组件 ({选择器: ''appchild',模板: '< h2 > {{_name}} </h2>'})导出类AppChildComponent实现OnInit {_name: string; 构造函数 (){}ngOnInit(){} @ Input()设置名称 (名称: string ){ 这。_姓名=(姓名& &name.trim())| | "我是默认名称";}获取名称 (){ 这个还回去。_姓名;}}
正如您在 @ Input() setter中注意到的那样,我们正在拦截从父级传递的值,并检查它是否是空字符串。如果它是空字符串,我们将为子组件中的名称分配默认值。
我们可以在父组件AppComponent中使用AppChildComponent,如下所示:
从 “@ angular/core” 导入 {Component};@ 组件 ({选择器: “ '我的应用程序 ”,模板: '< h1 > Hello {{message}} < /h1> <br/ < appchild * ngFor = “让n个childNameArray”[Name] = "n" > < /appchild> ',})导出类AppComponent { 消息: string = "我是父"childmessage : string = “ 我从父组件传递到子组件”childNameArray = ['foo','koo','','moo','too','hoo','' ];}
在父组件内部,我们通过childNameArray属性的所有项循环子组件。childNameArray的一些项目是空字符串,这些空字符串将由子组件setter拦截并设置为默认值。子组件将呈现从父组件传递的值,如下图所示:
ngOnChanges和 @ Input() 装饰器
我们可以使用组件的OnChanges生命周期钩子拦截任何输入属性更改。可能有各种原因,输入属性可以在父组件中更改,并且需要在子组件中拦截。这可以在OnChanges生命周期钩子上完成。
让我们想象一下,我们需要在一个名为counter的输入变量中记录更改。计数器的值由父组件设置,并且可以在父组件中更改。每当父组件中计数器的值发生更改时,我们需要记录子组件中的更改。我们创建了一个子组件,如下所示:
从 “@ angular/core” 导入 { Component,Input,OnChanges,SimpleChange};@ 组件 ({选择器: ''appchild',模板: '< h2 > {{counter}} </h2> < h2 > 值更改 </h2> < ul > <李*ngFor="让changeLog的c">{{c}}</li> < /ul> '})导出类AppChildComponent实现OnChanges { @ Input() 计数器 = 0;changeLog : string [] = []; 构造函数 (){} ngOnChanges(changes: {[propKey: string]: SimpleChange}){ 让日志: string [] = []; 对于 (让p在变化中) { 令c = 变化 [p];console.log(c); 让从 = JSON.stringify(c.previousValue); 让 = JSON.stringify(c.currentValue);log.push( '${p} 从 $ {f自} 更改为 ${to}' );} 这个 .changeLog.push(log.join( ', '));}}
基本上我们正在做以下:
- 实现OnChanges生命周期钩子
- 在ngOnChanges方法中,传递一个类型为SimpleChange的数组
- 遍历所有更改并将其推送到字符串数组
每当计数器的值将被改变,子组件将记录以前的值和当前值。每个输入属性的前一个值和当前值的读取在ngOnChnages方法中完成,如下图所示。
在父组件中,我们将分配一个新的随机数来计算按钮单击时的属性,并将count属性设置为子组件的输入属性计数器的值。
从 “@ angular/core” 导入 {Component};@ 组件 ({选择器: “ '我的应用程序 ”,模板: '< h1 > Hello {{message}} < /h1> <br/ <按钮 (单击)="nextCount()">更改计数</按钮> <br/> < appchild [counter] = "count" >< /appchild> ',})导出类AppComponent { 计数: 个数 = 0;nextCount(){console.log( "hahahah" ); 这个 .count = 这个。getRandomIntInclusive( 此 .count, 此 .count 1000 );}getRandomIntInclusive(min : number, max: number) {min = 数学。ceil(min);max = 数学。地板 (最大); 返回数学。地板 (数学。随机 () * (最大-最小1 )) 最小;}}
本质上,在父组件中,我们使用父组件的count属性设置子组件的输入属性计数器的值,并在每次单击按钮时更改其值。每当count属性值在父组件处更改时,计数器输入属性的值将在子组件中更改,并且将记录更改的值。
在运行应用程序时,我们可能会得到带有更改日志的预期输出,如下图所示:
结论
在本文中,我们学习了如何将数据从父组件传递到子组件。我们还学习了如何拦截输入消息并记录更改。在进一步的文章中,我们将探讨组件通信的更多方面。我希望你发现这篇文章有用,感谢阅读!