Angular2之组件交互和数据绑定

组件交互

组件间的交互包括父子组件交互和一些非父子关系组件的交互。父子组件之间的交互通过常用的有三种方式:

1. 通过Angualr的输入属性(@Input)和输出属性(@Output)

通过输入型绑定把数据从父组件传到子组件(@Input):

以下面代码为例,父组件HeroParentComponent将获取到的hero数据通过属性绑定的方式流向子组件HeroChildComponent,子组件通过@Input装饰器进行数据接收。@Input装饰器告诉Angular,该属性是公共的,并且能被父组件绑定。 如果没有@Input,Angular就会拒绝绑定到该属性。这里重点关注父组件的[myHero]="hero",等号右侧hero,它属于模板所在的组件,不需要@Input装饰器。
等号左边[myHero],该属性属于其它组件或指令,它必须在子组件中带有@Input 装饰器。

父组件:

import { Component } from '@angular/core';
import { HEROES } from './hero';
@Component({
  selector: 'hero-parent',
  template: `
    "let hero of heroes" [myHero]="hero">
    hero-child>
  `
})
export class HeroParentComponent {
  heroes = HEROES;
}

子组件:

import { Component, Input } from '@angular/core';
import { Hero } from './hero';
@Component({
  selector: 'hero-child',
  template: `
    

{ {myHero.name} } says:h3> <p>I, { {myHero.name} }, am at your service.p> ` }) export class HeroChildComponent { @Input() myHero: Hero;//通过@Input装饰器进行数据的接收 }

通过输出型绑定父组件监听子组件的事件(@Output):

使用事件传递是子组件向父组件传递数据最常用的方式。子组件需要实例化一个用来订阅和触发自定义事件的EventEmitter类,这个实例对象是一个由装饰器@Output修饰的输出属性。当用户期望操作行为发生时,可手动触发该事件,父组件则通过事件绑定的方式来订阅来自子组件触发的事件。

父组件:

import { Component }      from '@angular/core';
@Component({
  selector: 'vote-taker',
  template: `
    "let voter of voters" (onVote)="onVoted($event)">
    my-voter>
  `
})
export class VoteTakerComponent {
  agreed = 0;
  disagreed = 0;
  voters = ['Mr. IQ', 'Ms. Universe', 'Bombasto'];
  onVoted(agreed: boolean) {
    agreed ? this.agreed++ : this.disagreed++;
  }
}

子组件:

import { Component, EventEmitter, Output } from '@angular/core';
@Component({
  selector: 'my-voter',
  template: `
    

如上代码,子组件VoterComponent点击按钮会触发vote事件,在子组件中通过emit属性触发这个自定义事件,并将传入参数agreed,父组件(onVote)="onVoted($event)",等号左边onVote是在子组件中通过@Output修饰器暴露出来的实例对象,等号右边是父组件的onVoted事件。父组件绑定的onVoted事件通过$event对象来访问传入的agreed数据。


2. 通过模板局部变量

模板引用变量通常用来引用模板中的某个DOM元素,它还可以引用Angular组件或指令或Web Component。使用井号 (#) 来声明引用变量。 可以在模板中的任何地方引用模板引用变量。 如示例,#phone的意思就是声明一个名叫phone的变量来引用元素。声明在上的phone变量就是在模板另一侧的 `, styleUrls: ['demo.css'] }) export class CountdownViewChildParentComponent implements AfterViewInit { @ViewChild(CountdownTimerComponent) private timerComponent: CountdownTimerComponent; start() { this.timerComponent.start(); }//调用子组件的start方法 }

子组件:

import { Component} from '@angular/core';
@Component({
  selector: 'countdown-timer',
  template: '

{{message}}

'
}) export class CountdownTimerComponent implements OnInit, OnDestroy { message = ''; start() { this.countDown(); } private countDown() { //做一些事 } }


数据绑定

从使用模型-视图-控制器 (MVC) 或模型-视图-视图模型 (MVVM) 的经验中,很多开发人员都熟悉了组件和模板这两个概念。 在 Angular 中,组件扮演着控制器或视图模型的角色,模板则扮演视图的角色。这里主要介绍模板语法中的数据绑定:

1. 插值表达式

数据绑定最常见的形式就是插值,使用的是双大括号{ { } }的语法,插值表达式有几种常见用法:

  • 可以把计算后的字符串对标签的属性进行赋值。
<h3>
  { {title} }
  <img src="{ {heroImageUrl} }" style="height:30px">
h3>
  • 用相应组件属性的值来替换括号内的变量,如下例,Angular会用这个组件的title变量的值替换{ {title} }这部分,形如

    title的值

    ,并最终在页面中展示出来。
<h3>{ {title} }h3>
  • 可以调用宿主组件的方法,如下例调用了组件的getVal方法。
<p>The sum of 1 + 1 is not { {1 + 1 + getVal()} }p>

插值表达式可以理解为一个有带计算功能的的语法。

2. 属性绑定

数据绑定一种单向的数据绑定,数据从组件流向模板。当要把一个视图元素的属性设置为模板表达式时,就需要用到属性绑定。属性绑定大致可分为四类:

  • DOM元素属性绑定

  • HTML标签特性绑定

  • CSS类绑定

  • Style样式绑定

其实属性绑定和插值在本质上没有区别,在渲染视图之前,Angular会将插值表达式转换成属性绑定的形式,它只是属性绑定的一种语法糖。如下示例这两种写法是等价的:

<div>{{hello}}div>
<div [innerHTML]="hello">div>

3. 事件绑定

事件绑定也是一种单向数据绑定形式,数据从模板流向组件类。事件绑定的语法是由“=”左侧小括号内的目标事件和“=”右侧引号中的模板语句组成。在事件绑定中,Angular通过监听用户操作事件,比如键盘事件,鼠标事件等来执行其对应绑定的方法。

<a class="edit" (click)="editContact()">编辑a>

如上示例,用事件绑定来监听按钮的点击事件,只要触发点击事件,就会调用组件的editContact()方法。

4. 双向数据绑定

如上文所说,属性绑定实现了数据从组件类流向模板,事件绑定则实现了数据从模板流向组件类,将这两者结合起来,就实现了双向绑定的效果。双向绑定语法实际上是属性绑定和事件绑定的语法糖。使用Angular提供的NgModel指令可以方便地实现双向绑定:

<input [(ngModel)]="currentUser" neme="currentUser" />

如上代码,当组件类中的变量currentUser发生变化的时候,会使input的value值自动发生变化。而当input的value值发生变化时,组件类中的变量currentUser也会自动发生变化。需要注意的是:在ng2中使用ngModel必须带有name属性或者使用 [ngModelOptions]=”{standalone: true}”,如果未设置name或者ngModelOptions,就会报错。


上文为本人的笔记总结,如有错误,欢迎指正:)

你可能感兴趣的:(Angular2)