Maison >interface Web >js tutoriel >Parlons de la façon de communiquer entre les composants dans Angular
Cet article vous aidera à continuer à apprendre angular et à découvrir les méthodes de communication des composants dans Angular. J'espère qu'il vous sera utile !
Dans l'article précédent, nous avons parlé de Angular combiné avec NG-ZORRO pour un développement rapide. Le développement front-end est en grande partie basé sur les composants et est toujours indissociable de la communication entre les composants. Alors, dans le développement Angular
, quelle est la communication entre ses composants ? [Recommandations de didacticiel associées : "Angular
开发中,其组件之间的通信是怎么样的呢?【相关教程推荐:《angular教程》】
举一反三,
Vue
和React
中大同小异
本文纯文字,比较枯燥。因为控制台打印的东西比较鸡肋,所以就不配图了,嗯~希望读者跟着说明代码走一遍更容易吸收~
相当于你自定义了一个属性,通过组件的引入,将值传递给子组件。Show you the CODE
。
<!-- parent.component.html --> <app-child [parentProp]="'My kid.'"></app-child>
在父组件中调用子组件,这里命名一个 parentProp
的属性。
// child.component.ts import { Component, OnInit, Input } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'] }) export class ChildComponent implements OnInit { // 输入装饰器 @Input() parentProp!: string; constructor() { } ngOnInit(): void { } }
子组件接受父组件传入的变量 parentProp
,回填到页面。
<!-- child.component.html --> <h1>Hello! {{ parentProp }}</h1>
通过 new EventEmitter()
将子组件的数据传递给父组件。
// child.component.ts import { Component, OnInit, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'] }) export class ChildComponent implements OnInit { // 输出装饰器 @Output() private childSayHi = new EventEmitter() constructor() { } ngOnInit(): void { this.childSayHi.emit('My parents'); } }
通过 emit
通知父组件,父组件对事件进行监听。
// parent.component.ts import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-communicate', templateUrl: './communicate.component.html', styleUrls: ['./communicate.component.scss'] }) export class CommunicateComponent implements OnInit { public msg:string = '' constructor() { } ngOnInit(): void { } fromChild(data: string) { // 这里使用异步 setTimeout(() => { this.msg = data }, 50) } }
在父组件中,我们对 child
组件来的数据进行监听后,这里采用了 setTimeout
的异步操作。是因为我们在子组件中初始化后就进行了 emit
,这里的异步操作是防止 Race Condition
竞争出错。
我们还得在组件中添加 fromChild
这个方法,如下:
<!-- parent.component.html --> <h1>Hello! {{ msg }}</h1> <app-child (childSayHi)="fromChild($event)"></app-child>
我们通过操纵引用的方式,获取子组件对象,然后对其属性和方法进行访问。
我们先设置子组件的演示内容:
// child.component.ts import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'] }) export class ChildComponent implements OnInit { // 子组件的属性 public childMsg:string = 'Prop: message from child' constructor() { } ngOnInit(): void { } // 子组件方法 public childSayHi(): void { console.log('Method: I am your child.') } }
我们在父组件上设置子组件的引用标识 #childComponent
:
<!-- parent.component.html --> <app-child #childComponent></app-child>
之后在 javascript
文件上调用:
import { Component, OnInit, ViewChild } from '@angular/core'; import { ChildComponent } from './components/child/child.component'; @Component({ selector: 'app-communicate', templateUrl: './communicate.component.html', styleUrls: ['./communicate.component.scss'] }) export class CommunicateComponent implements OnInit { @ViewChild('childComponent') childComponent!: ChildComponent; constructor() { } ngOnInit(): void { this.getChildPropAndMethod() } getChildPropAndMethod(): void { setTimeout(() => { console.log(this.childComponent.childMsg); // Prop: message from child this.childComponent.childSayHi(); // Method: I am your child. }, 50) } }
这种方法有个限制?,就是子属性的修饰符需要是 public
,当是 protected
或者 private
的时候,会报错。你可以将子组件的修饰符更改下尝试。报错的原因如下:
类型 | 使用范围 |
---|---|
public | 允许在累的内外被调用,作用范围最广 |
protected | 允许在类内以及继承的子类中使用,作用范围适中 |
private | 允许在类内部中使用,作用范围最窄 |
我们结合 rxjs
来演示。
rxjs 是使用 Observables
的响应式编程的库,它使编写异步或基于回调的代码更容易。
后期会有一篇文章记录
rxjs
,敬请期待
我们先来创建一个名为 parent-and-child
的服务。
// parent-and-child.service.ts import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; // BehaviorSubject 有实时的作用,获取最新值 @Injectable({ providedIn: 'root' }) export class ParentAndChildService { private subject$: BehaviorSubject<any> = new BehaviorSubject(null) constructor() { } // 将其变成可观察 getMessage(): Observable<any> { return this.subject$.asObservable() } setMessage(msg: string) { this.subject$.next(msg); } }
接着,我们在父子组件中引用,它们的信息是共享的。
// parent.component.ts import { Component, OnDestroy, OnInit } from '@angular/core'; // 引入服务 import { ParentAndChildService } from 'src/app/services/parent-and-child.service'; import { Subject } from 'rxjs' import { takeUntil } from 'rxjs/operators' @Component({ selector: 'app-communicate', templateUrl: './communicate.component.html', styleUrls: ['./communicate.component.scss'] }) export class CommunicateComponent implements OnInit, OnDestroy { unsubscribe$: Subject<boolean> = new Subject(); constructor( private readonly parentAndChildService: ParentAndChildService ) { } ngOnInit(): void { this.parentAndChildService.getMessage() .pipe( takeUntil(this.unsubscribe$) ) .subscribe({ next: (msg: any) => { console.log('Parent: ' + msg); // 刚进来打印 Parent: null // 一秒后打印 Parent: Jimmy } }); setTimeout(() => { this.parentAndChildService.setMessage('Jimmy'); }, 1000) } ngOnDestroy() { // 取消订阅 this.unsubscribe$.next(true); this.unsubscribe$.complete(); } }
import { Component, OnInit } from '@angular/core'; import { ParentAndChildService } from 'src/app/services/parent-and-child.service'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'] }) export class ChildComponent implements OnInit { constructor( private parentAndChildService: ParentAndChildService ) { } // 为了更好理解,这里我移除了父组件的 Subject ngOnInit(): void { this.parentAndChildService.getMessage() .subscribe({ next: (msg: any) => { console.log('Child: '+msg); // 刚进来打印 Child: null // 一秒后打印 Child: Jimmy } }) } }
在父组件中,我们一秒钟之后更改值。所以在父子组件中,一进来就会打印 msg
的初始值 null
,然后过了一秒钟之后,就会打印更改的值 Jimmy
Tutoriel angulaire
Déduisez d'autres cas à partir d'un exemple,Vue
etReact
sont similaires avec quelques différences mineures1. . Le composant parent transmet l'attribut Passer des valeurs aux sous-composants
équivaut à personnaliser une propriété et à transmettre la valeur aux sous-composants via l'introduction du composant.Montrez-vous le CODE
. 🎜rrreee🎜Appelez le composant enfant dans le composant parent, nommez ici un attributparentProp
. 🎜rrreee🎜Le composant enfant accepte la variableparentProp
transmise par le composant parent et la remplit dans la page. 🎜rrreee2. Le composant enfant transmet les informations au composant parent via l'événement Emitter
🎜Grâce ànew EventEmitter() Transmettez les données du composant enfant au composant parent. 🎜rrreee🎜Avertissez le composant parent via <code>emit
, et le composant parent écoute l'événement. 🎜rrreee🎜Dans le composant parent, après avoir surveillé les données du composantchild
, nous utilisons l'opération asynchrone desetTimeout
. C'est parce que nous avons effectuéemit
après l'initialisation du sous-composant. L'opération asynchrone ici consiste à éviter les erreurs de compétitionRace Condition
. 🎜🎜Nous devons également ajouter la méthodefromChild
dans le composant, comme suit : 🎜rrreee3. Par référence, le composant parent obtient. Propriétés et méthodes du composant enfant
🎜Nous obtenons l'objet sous-composant en manipulant la référence, puis accédons à ses propriétés et méthodes. 🎜🎜Nous définissons d'abord le contenu démo du composant enfant : 🎜rrreee🎜Nous définissons l'identifiant de référence du composant enfant#childComponent
sur le composant parent : 🎜rrreee🎜Puis sur lejavascript fichier Appel : 🎜rrreee🎜Y a-t-il une limitation à cette méthode ? Autrement dit, le modificateur de la sous-propriété doit être <code>public
, lorsqu'il estprotégé
. ouprivé
Parfois, une erreur sera signalée. Vous pouvez essayer de changer le modificateur du sous-composant. La raison de l'erreur est la suivante : 🎜
Type Plage d'utilisation public Permet d'être appelé à l'intérieur et à l'extérieur de la classe, avec la portée la plus large protégé Permet d'être appelé au sein de la classe Et utilisé dans les sous-classes héritées, la portée est modéréeprivée Il est autorisé à être utilisé à l'intérieur de la classe , la portée est la plus étroite tr>4 Changement via le service
. 🎜Nous combinonsrxjs
pour démontrer. 🎜🎜rxjs est une bibliothèque de programmation réactive utilisantObservables
, ce qui facilite l'écriture de code asynchrone ou basé sur un rappel. 🎜🎜Il y aura un article enregistrant🎜Créons d'abord un service nommérxjs
plus tard, alors restez à l'écoute🎜parent-and-child
. 🎜rrreee🎜Ensuite, nous le référençons dans les composants parent et enfant, et leurs informations sont partagées. 🎜rrreeerrreee🎜Dans le composant parent, nous modifions la valeur après une seconde. Ainsi dans le composant parent-enfant, la valeur initialenull
demsg
sera imprimée dès son arrivée, puis après une seconde, la valeur modifiéeJimmy
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!