组件间数据共享是angular必须要理解的基础概念,本文介绍四种不同的共享式。
angular的父子兄弟组件
父组件到子组件:通过@Input()进行数据共享
这是最常用直观的数据共享方式。使用@Input()
修饰符通过模板进行数据传递。
parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<app-child [childMessage]="parentMessage"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent{
parentMessage = "message from parent"
constructor() { }
}
child.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: `
Say {{ message }}
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
@Input() childMessage: string;
constructor() { }
}
子组件到父组件:通过 ViewChild 进行数据共享
ViewChild
允许从一个组件注入到另一个,父组件可以访问子组件的参数和方法。但是,在视图初始化之前,该子项将不可用。这意味着我们需要实现AfterViewInit生命周期钩子来接收来自子生命周期的数据(这块我也不太理解)。
parent.component.ts
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from "../child/child.component";
@Component({
selector: 'app-parent',
template: `
Message: {{ message }}
<app-child></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) child;
constructor() { }
message:string;
ngAfterViewInit() {
this.message = this.child.message
}
}
child.component.ts
import { Component} from '@angular/core';
@Component({
selector: 'app-child',
template: `
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message = 'Hola Mundo!';
constructor() { }
}
子组件到父组件:通过 Output()和EventEmitter进行数据共享
另外一种方式是通过在子组件里emit数据到父组件里。这种一般用在子组件进行按钮单击、表单提交或其他用户事件产生数据变化时触发的向父组件的数据共享。父组件需要建立一个函数来接收消息为变量赋值。
在下面的样例中我们定义一个带Output修饰符的messageEvent变量并实例化成一个emitter。然后创建一个名为sendMessage的函数调用emit事件发送消息数据。最后创建一个按钮触发这个函数。
父组件通过订阅(subscribe)到子组建的messageEvent输出,然后在子组件按下按钮后触发消息数据接收函数。
parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
Message: {{message}}
<app-child (messageEvent)="receiveMessage($event)"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
message:string;
receiveMessage($event) {
this.message = $event
}
}
child.component.ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message: string = "Hola Mundo!"
@Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
其他组件间数据共享方式
非直连组件间数据传值应该通过在共享服务层加入RxJS BeahaviorSubject。
在可以用RxJS其他Subject通过服务层共享数据时为什么要选择用BehaviorSubject?
1.订阅后会返回当前值 ,不需要调用onnext
2.通过getValues()函数提取最后值做为raw data。
3.确保组件能收到最新的数据。
在以下服务中,创建一个私有BehaviorSubject提供消息数据。首先定义一个currentMessage变量存放observable数据流,然后创建一个组件里的函数来改变变量值。
父、子、兄弟组件在订阅后都会收到相同的变量值。把DataService注入到contructor中,然后订阅其中的currentMessage observable来接收信息。
组件中创建一个发送消息函数广播到其他组件中接收函数进行数据接收。
data.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
this.messageSource.next(message)
}
}
parent.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'app-parent',
template: `
{{message}}
`,
styleUrls: ['./sibling.component.css']
})
export class ParentComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
}
sibling.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'app-sibling',
template: `
{{message}}
<button (click)="newMessage()">New Message</button>
`,
styleUrls: ['./sibling.component.css']
})
export class SiblingComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
newMessage() {
this.data.changeMessage("Hello from Sibling")
}
}
网友评论