Angular2 组件通讯

原文:http://www.cnblogs.com/SLchuck/p/5904000.html

1. 组件通讯

咱们知道Angular2应用程序其实是有不少父子组价组成的组件树,所以,了解组件之间如何通讯,特别是父子组件之间,对编写Angular2应用程序具备十分重要的意义,一般来说,组件之间的交互方式主要有以下几种:html

l 使用输入型绑定,把数据从父组件传到子组件框架

l 经过 setter 拦截输入属性值的变化ide

l 使用 ngOnChanges 拦截输入属性值的变化函数

l 父组件监听子组件的事件this

l 父组件与子组件经过本地变量互动spa

l 父组件调用 ViewChildhtm

l 父组件和子组件经过服务来通信对象

本文会经过讲解着几种方式来对组件之间的通讯作一个大体的介绍。blog

2. 输入型绑定

输入型绑定指的是利用模板语法中的属性型绑定方式,将父组件的数据传递到子组件对应的对象中,子组件中的对象通常使用@Input装饰器来修饰,做为数据的接受者,例如接口

@Component({

selector: 'child',

template: 'I am fron {{input}}'

})

export class ChildComponent implements OnInit {

@Input()

input;

constructor() { }

ngOnInit() { }

}

@Component({

selector: 'parent',

template: '<child [input]="data"></child>'

})

export class ParentComponent implements OnInit {

data: string;

constructor() { }

ngOnInit() {

this.data = "parent";

}

}

以上的例子咱们能够看出,存在父子两个组件,在父组件ParentComponent中的模板中引入了<child [input]="data"></child>子组件,并将data数据经过属性绑定的方式绑定到input属性中传入到子组件中,子组件中经过@Input()注解修饰input属性来接收传入的数据,并显示在模板I am fron {{input}}中。

输入型绑定是从父组件传递数据到子组件最多见的方式。

3. setter监听

咱们知道,Angular2是一个MVVM的框架,当数据发生变化时可以同步显示到模板视图中,可使用一个输入属性的 setter 函数,以拦截父组件中值的变化,并采起行动。例如,咱们改造上面的例子,子组件中使用set,get重写对应的绑定input属性,当输入值方式变化时输出一个控制台信息。

@Component({

selector: 'child',

template: 'I am fron {{data}}'

})

export class ChildComponent implements OnInit {

_input:string;

@Input()

public set input(v : string) {

this._input = v;

console.log(v);

}

public get input() : string {

return this._input;

}

constructor() { }

ngOnInit() { }

}

4. ngOnChanges

除了上面说的setter函数能够响应输入数据的变化外,Angular2还提供了一个生命周期函数ngOnChanges 能够监听数据的变化。使用 OnChanges 生命周期钩子接口的 ngOnChanges 方法来监测输入属性值的变化并作出回应。咱们改造以上的子组件来响应对应的变化,在这个示例中,咱们监听了输入数据的变化,采起的对应动做仅仅是输出对应的信息,固然你也能够作不少其余的事情。

@Component({

selector: 'child',

template: 'I am fron {{data}}'

})

export class ChildComponent implements OnInit, OnChanges {

_input: string;

@Input()

public set input(v: string) {

this._input = v;

console.log(v);

}

public get input(): string {

return this._input;

}

constructor() { }

ngOnInit() { }

ngOnChanges(changes: SimpleChanges) {

console.log(changes);

}

}

5. 事件传播

上面的集中方式都是父组件如何向子组件传递数据以及子组件如何监听数据的变化,事件传播则是子组件如何向父组件通讯的一种方式。子组件暴露一个 EventEmitter 属性,当事件发生时,子组件利用该属性 emits( 向上弹射 ) 事件。父组件绑定到这个事件属性,并在事件发生时做出回应。子组件的 EventEmitter 属性是一个 输出属性 ,一般带有 @Output 装饰器 。

@Component({

selector: 'child',

template: `

I am fron {{data}}<br />

<button id="out" (click)="click()">click for out</button>

`

})

export class ChildComponent implements OnInit, OnChanges {

_input: string;

@Input()

public set input(v: string) {

this._input = v;

console.log(v);

}

public get input(): string {

return this._input;

}

@Output()

output:EventEmitter<string> = new EventEmitter<string>();

click(){

this.output.emit("i am from child");

}

constructor() { }

ngOnInit() { }

ngOnChanges(changes: SimpleChanges) {

console.log(changes);

}

}

@Component({

selector: 'parent',

template: '<child [input]="data" (output)="output($event)"></child>'

})

export class ParentComponent implements OnInit {

data: string;

constructor() { }

ngOnInit() {

this.data = "parent";

}

output($event){

console.log($event);

}

}

在上面的例子中,咱们在子组件ChildComponent添加了一个向外传播的事件output:EventEmitter<string> = new EventEmitter<string>(),并添加了一个点击的按钮,当按钮事件触发时,就会调用output事件向父组件传递事件,并将数据做为参数传递到父组件ParentComponent中,同时在父组件ParentComponent的模板<child [input]="data" (output)="output($event)"></child>中能够看到,咱们使用模板语法中的事件绑定,绑定了output函数做为对应事件的接受函数,当子组件output事件触发是,父组件的函数就会获得执行。

使用事件传播来进行子组件对父组件之间的通讯是最多见的方式。

6. 本地变量

在模板语法中,咱们知道存在着本地变量这种语法,可使用本地变量来表明对应的组件。虽然父组件不能使用数据绑定来读取子组件的属性或调用子组件的方法。但能够在父组件模板里,新建一个本地变量来表明子组件,而后利用这个变量来读取子组件的属性和调用子组件的方法,不过这种使用方式只能在模板中使用,例如以下所示,改写上面例子中的父组件模板,代码以下。

咱们在ParentComponent组件中使用本地变量#child获取了child组件的实例,这样就能够在模板中使用其属性或者方法,例如child.input。

@Component({

selector: 'parent',

template: '<child [input]="data" (output)="output($event)" #child></child>{{child.input}}'

})

export class ParentComponent implements OnInit {

data: string;

constructor() { }

ngOnInit() {

this.data = "parent";

}

output($event){

console.log($event);

}

}

7. ViewChild

本地变量的方式是在父组件的模板中获取子组件的实例,有木有其余方式能够在组件的类中获取子组件的实例呢?答案是确定的,若是父组件的类须要读取子组件的属性值或调用子组件的方法,就不能使用本地变量方法。当父组件类 须要这种访问时,能够把子组件做为ViewChild,注入到父组件里面。例如,咱们改造上面的父组件的组件类,使用ViewChild来获取子组件的实例,代码以下:

@Component({

selector: 'parent',

template: '<child [input]="data" (output)="output($event)" #child></child>{{child.input}}'

})

export class ParentComponent implements OnInit {

@ViewChild(ChildComponent)

private childComponent: ChildComponent;

data: string;

constructor() { }

ngOnInit() {

this.data = "parent";

}

output($event) {

console.log($event);

}

}

在以上的代码中,咱们使用@ViewChild(ChildComponent)注解的形式获取了对应子组件childComponent的实例,这样在父组件类中就能够调用子组件对应的属性及方法了。

相对于本地变量的方式而言,ViewChild的方式更加灵活,用途也比较普遍。可是,须要注意的一点是,必须等待父组件的视图显示完成后才可使用,所以,ngAfterViewInit 生命周期钩子是很是重要的一步。

8. 服务方式

经过服务依赖注入的方式,咱们能够了解到,服务在父子组件之间是能够共享的,所以,咱们能够利用共享的服务的形式在父子组件之间进行通讯。

若是咱们将服务实例的做用域被限制在父组件和其子组件内,这个组件子树以外的组件将没法访问该服务或者与它们通信。

通常来讲,父子之间使用服务的方式来通行,是采用事件消息的形式来实现的。

例如,以下的代码中,父子组件中共享了Service服务,并在各自的类中获取了Service服务的实例,当分别点击父子组件中的按钮时,就可以触发Service服务中的对应的input$以及output$,由于服务是共享的,因此在父子组件中监听对应的服务信息,就可以获得传递的消息。

@Injectable()

export class Service {

input$: EventEmitter<string> = new EventEmitter<string>();

output$: EventEmitter<string> = new EventEmitter<string>();

constructor() {

}

}

@Component({

selector: 'child',

template: `

<button id="out" (click)="click()">click for output</button>

`

})

export class ChildComponent {

constructor(private _service: Service) {

this._service.input$.subscribe(function (input: string) {

console.log(input);

})

}

click() {

this._service.output$.emit('i am from child');

}

}

@Component({

selector: 'parent',

template: '<child></child><button id="input" (click)="click()">click for input</button>',

providers: [Service]

})

export class ParentComponent {

constructor(private _service: Service) {

this._service.output$.subscribe(function (output: string) {

console.log(output);

})

}

click() {

this._service.input$.emit('i am from child');

}

}

相关文章
相关标签/搜索