五:Angular 数据绑定 (Data Binding)

通常来说,数据绑定要么是从页面流向组件中的数据,要么是从组件中的数据流向页面。下面我们来介绍在Angular 2中数据绑定的几种不同方式。 
1. 使用{{}}将组件中的数据显示在html页面上 
  实现方式:<div>{{value}}</div> 
  这样就可将组件中的value值显示在div元素上。 
2. 使用[]DOM元素的属性值设置为组件中的数据 
  实现方式:<img [src]="srcUrl"> 
  这样就可以将img标签的src属性设置为组件中的srcUrl值。但是使用[]只能绑定在DOM元素已有的属性上,例如<div [src]="srcUrl"></div>是会报错的,以为div不存在src属性。 
  但是,可以通过自定义的方式使用@Input为我们的指令添加属性,这也是实现从父子组件数据通信的一种方式,顾名思义就是@Input定义的属性值是从父组件中获取的。 
  下面我们来介绍使用@Input实现数据绑定。

//父组件
@Component({
    selector: 'my-app',
    template: `<customer-counter [counter] = "someValue"></customer-counter>`,
    directives:[CustomerCounterComponent]
})

export class AppComponent{
    someValue = 3;
}

//子组件
@Component({
    selector: 'customer-counter',
    template: `<span>{{counter}}</span>`
})

export class CustomerCounterComponent{
    counterValue = 0;
    @Input()
    get counter(){
        return this.counterValue;
    }
}

  这样<customer-counter [counter] = "someValue"></customer-counter>就可以将父组件中的someValue数据绑定在子组件的counter属性上了。 
3. 事件绑定 
  事件绑定就是通过用户的交互行为来触发DOM元素的事件。 
  例如:<button (click)="onClickMe()">点我!</button> 
  当用户点击button是就会触发onClickMe()方法,这样实现的前提是button能够监听click方法。 
  当然,也可以通过@Output在我们的组件中添加自定义事件,@Output顾名思义就是在子组件中向父组件输出东西。 
  具体实现如下:

//父组件
@Component({
    selector: 'my-app',
    template: `<customer-counter (counterChange) = "changeValue($event)"></customer-counter> <div>{{someValue}}</div>`,
    directives:[CustomerCounterComponent]
})

export class AppComponent{
    someValue = 3;
    changeValue(val){
        this.someValue = val;
    }
}

//子组件
@Component({
    selector: 'customer-counter',
    template: `<button (click)="decrement()">-</button>`
})

export class CustomerCounterComponent{
    counterValue = 100;
    @Output() counterChange = new EventEmitter();
    decrement() {
        this.counterChange.emit(-- this.counterValue );
    }
}

 这样<customer-counter (counterChange) = "changeValue($event)"></customer-counter>当子组件中的counterChange事件被触发,就会执行父组件中的changeValue()方法,进而改变父组件中的相关数据。 
4. 双向绑定 
  上面介绍的方式{{}}和[]是将组件中的数据绑定到DOM元素上,而()是将组件中的事件绑定到组件中的方法上,那么该如何数据的双向绑定呢? 
  Angular2是通过[()]来实现的,例如<input [(ngModel)]="value">就是双向绑定input元素的值。但是需要注意的是[()]只能绑定在有输入输出功能的DOM元素上(例如:input、textare),如果绑定在div这样的元素上就会报错。 
  那么,如何通过[()]在我们自定义的指令上实现双向绑定呢?没错,就是使用@Input和@Output来实现。

//父组件
@Component({
    selector: 'my-app',
    template: `
<customer-counter [(counter)] = "someValue"></customer-counter> <p> value: {{someValue}}</p>`,
    directives:[CustomerCounterComponent]
})

export class AppComponent{
    someValue = 3;
}
//子组件
@Component({
    selector: 'customer-counter',
    template: `<button (click)="decrement()">-</button> <span>{{counter}}</span>`
})

export class CustomerCounterComponent{
    counterValue = 0;
    @Input()
    get counter(){
        return this.counterValue;
    }
    @Output() counterChange = new EventEmitter();
    set counter(val) {
        this.counterValue = val;
        this.counterChange.emit(this.counterValue);
    }
    decrement() {
        this.counter--;
    }
}

  这样<customer-counter [(counter)] = "someValue"></customer-counter>就可以将父组件中的someValue绑定到子组件的counter属性上,同时当子组件的counter属性发生改变时也更新父组件的someValue值。 
  需要注意的是,我们定义的事件监听是counterChange,而使用的确实[(counter)]。这是因为Angular 2中约定添加后缀Change,也就是[(counter)]等价于[change]和(counterChange)的组合。如果去看[(ngModel)]的实现,你也会发现它是[ngModel]和[ngModelChange]的组合。

 

posted @ 2018-08-01 11:05  你过来啊!  阅读(662)  评论(0编辑  收藏  举报