Today's front-end development is moving closer to the component-based development model. If you use the most popular front-end frameworks Angular and React to develop applications, it is inevitable that components will be developed, which means we need to consider issues such as data transfer between components. However, Angular 2 has provided us with a good solution.
Parent and child components
Developers who have been exposed to object-oriented programming will definitely not be unfamiliar with the parent-son relationship. In Angular 2, child components exist in the parent-son component "in the body", and parent-son components can communicate through some channels.
Parent component passes data to child component – @Input
When we start developing a component, the first thing that comes to mind is to pass in data for it. After all, we expect that components usually need to provide "nutrition" for us to handle certain tasks. After all, we cannot let the horse run away and not give it grass. Angular 2 child components use the decorator @Input to receive the data passed in by the parent component:
// import { OnInit, Component, Input } from '@angular/core'; @Component({ selector: 'child-component', ... }) export class ChildComponent implements OnInit { @Input count: number = 0; ngOnInit() { (); // The value passed in the parent component or the initial value we set ourselves 0 } increaseNumber() { ++; } descreaseNumber() { --; } }
As you can see, we use the decorator @Input to modify the count attribute, which means that when the child-component is used, we expect to receive a property called count. Of course, we should be careful when others use our components. Any situation may occur when others use our components, so we set an initial value for count. When the parent component does not pass the value to our count attribute, we take this initial value.
// import { Component } from '@angular/core'; import { ChildComponent } from '../child-component/child-component'; @Component({ template: ` <child-component [count]='initialCount'></child-component> `, ... }) export class FatherComponent { initialCount: number = 5; }
When the parent component uses child-component, the initial value initialCount is assigned to the count property, that is, 5, which means that 5 will be printed in the ngOnInit method of ChildComponent. Note that the [count] syntax identifies the data flow direction: the parent component flows into the child component, that is, one-way data binding. At this time, if the data passed in is a basic data type, any operation on the array in the child component will not affect the parent component. However, if the data passed in is not the basic data type, but the data type is referenced, pay special attention to the operation on the data in the child component may have an impact on the parent component.
The child component notifies the parent component that the data has been processed – @Output, EventEmitter
After the parent component passes data to the child component, everything will not be fine. Just like parents raise children to study, the children need to present their study progress, test scores, etc. to their parents (regardless of whether they are voluntarily or not). The parent component also needs the child component to notify themselves at the right time that the data has been processed and can be reviewed. At this time, you need to use @Output and EventEmitter.
// import { Component } from '@angular/core'; import { ChildComponent } from '../child-component/child-component'; @Component({ template: ` <child-component [count]='initialCount' (change)="countChange($event)"></child-component> `, ... }) export class FatherComponent { initialCount: number = 5; countChange($event) { } }
Let's see what we have added to the parent component:
1. (change), when you see such a syntax, you will know that this is event binding at the first time, that is, we listen to certain changes in the child component in the parent component and can make related operations when it changes;
2. Added the countChange method as the handler of the change event.
But wait, when we specify attributes such as type, placeholder, etc. for the input tag, we know that they have been "implemented". The so-called "implementation", that is, these attributes make sense on the input tag. But it doesn't make sense for us to specify an event named change for the child-component, because it does not "implement" the change event, so the next step is to make it meaningful using @Output and EventEmitter:
// import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'child-component', ... }) export class ChildComponent { @Input count: number = 0; @Output change = new EventEmitter(); increaseNumber() { ++; (); } descreaseNumber() { --; (); } }
Let's take a look at what is added to the child component:
1. Use the decorator @Output to modify the change attribute and assign it an instance with the initial value of EventEmitter;
2. After the increaseNumber and decreaseNumber methods have modified the count attribute, the emit method of the change attribute is called to notify the parent component.
At this time, we implemented change in ChildComponent, so it makes sense to bind the change event for the child-component in the parent component: When the child component notifies the parent component, the parent component can obtain the data carried in the notification and perform the next operation:
// ... countChange($event) { = $event; } ...
Summarize
I don’t know if you have found it. In fact, we simulated "two-way data binding" above: the parent component passes data into the child component, and notifies the parent component for "synchronous update" when the child component changes the data. However, it should be noted that the data flow is actually unidirectional, that is, the data flows into the child component in one-way direction, and the update of the parent component data is only updated after notification of the child component's event. In other words, in Angular 2, two-way data binding = one-way data binding + event, taking the ngModel we are most familiar with as an example:
<input type='text' name='userName' [(ngModel)]="userName">
It is equivalent to the following writing method:
<input type='text' name='userName' [ngModel]="userName" (ngModelChange)="userName=$event">
Similarly, if we write our child-component component into the form of bidirectional data binding, it is:
<child-component [(count)]='initialCount'></child-component>
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.