Angular中Input和Output的介绍(附代码)
Input 是属性装饰器,用来定义组件内的输入属性。在实际利用场合,我们主要用来实现父组件向子组件传递数据。Angular 利用是由林林总总的组件组成,当利用启动时,Angular 会从根组件开端启动,并解析整棵组件树,数据由上而下贱下下1级子组件。
@Input()
counter.component.ts import { Component, Input } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>当前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input() count: number = 0; increment() { this.count++; } decrement() { this.count--; } }
app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <exe-counter [count]="initialCount"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; }
@Input(‘bindingPropertyName’)
Input 装饰器支撑一个可选的参数,用来指定组件绑定属性的名称。假如没有指定,则默许使用 @Input 装饰器,装饰的属性名。详细示例如下:
counter.component.ts
import { Component, Input } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>当前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input('value') count: number = 0; ... // 其余代码未改动 }
app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <exe-counter [value]="initialCount"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; }
setter & getter
setter 和 getter 是用来束缚属性的设定和猎取,它们供给了一些属性读写的封装,可以让代码更便利,更具可扩展性。通过 setter 和 getter 方式,我们对类中的私有属性停止了封装,能幸免外界操纵影响到该私有属性。此外通过 setter 我们还可以封装一些业务逻辑,详细示例如下:
counter.component.ts
import { Component, Input } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>当前值: {{ count }} </p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { _count: number = 0; // 默许私有属性以下划线开头,不是必需也可以使用$count biggerThanTen: boolean = false; @Input() set count (num: number) { this.biggerThanTen = num > 10; this._count = num; } get count(): number { return this._count; } increment() { this.count++; } decrement() { this.count--; } }
ngOnChanges
当数据绑定输入属性的值发生转变的时候,Angular 将会主动调取 ngOnChanges 办法。它会获得一个 SimpleChanges 对象,包括绑定属性的新值和旧值,它主要用于监测组件输入属性的转变。详细示例如下:
import { Component, Input, SimpleChanges, OnChanges } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>当前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent implements OnChanges{ @Input() count: number = 0; ngOnChanges(changes: SimpleChanges) { console.dir(changes['count']); } increment() { this.count++; } decrement() { this.count--; } }
上面例子中需要留意的是,当手动改动输入属性的值,是不会触发 ngOnChanges 钩子的。
Output 是属性装饰器,用来定义组件内的输出属性。前面我们介绍了 Input 装饰器的作用,也理解了当利用启动时,Angular 会从根组件开端启动,并解析整棵组件树,数据由上而下贱下下1级子组件。而我们今天介绍的 Output 装饰器,是用来实现子组件将信息通过事件的情势通知到父级组件。
在介绍 Output 属性装饰器前,我们先来介绍一下 EventEmitter 这个幕后英雄。它用来触发自定义事件,详细使用示例如下:
let numberEmitter: EventEmitter<number> = new EventEmitter<number>(); numberEmitter.subscribe((value: number) => console.log(value)); numberEmitter.emit(10);
在 Angular 中的 EventEmitter 利用场景是:
子指令创立一个 EventEmitter 实例,并将其作为输出属性输出。子指令调取已创立的 EventEmitter 实例中的 emit(payload) 办法来触发一个事件,父指令通过事件绑定 (eventName) 的方式监听该事件,并通过 $event 对象来猎取 payload 对象。是不是感受有点抽象,我们立刻实战一下。
@Output()
counter.component.ts import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>当前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input() count: number = 0; @Output() change: EventEmitter<number> = new EventEmitter<number>(); increment() { this.count++; this.change.emit(this.count); } decrement() { this.count--; this.change.emit(this.count); } }
app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <p>{{changeMsg}}</p> <exe-counter [count]="initialCount" (change)="countChange($event)"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; changeMsg: string; countChange(event: number) { this.changeMsg = `子组件change事件已触发,当前值是: ${event}`; } }
@Output(‘bindingPropertyName’)
Output 装饰器支撑一个可选的参数,用来指定组件绑定属性的名称。假如没有指定,则默许使用 @Output 装饰器,装饰的属性名。详细示例如下:
counter.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>当前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input() count: number = 0; @Output('countChange') change: EventEmitter<number> = new EventEmitter<number>(); ... // 其余代码未改动 }
app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <p>{{changeMsg}}</p> <exe-counter [count]="initialCount" (countChange)="countChange($event)"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; changeMsg: string; countChange(event: number) { this.changeMsg = `子组件change事件已触发,当前值是: ${event}`; } }
双向绑定
在介绍双向绑定此前,我们先来说个需求:即在 CounterComponent 子组件 count 值发生转变的时候,需同步更新 AppComponent 父组件中的 initialCount 的值。通过上面的实例,我们知道我们可以在 AppComponent 父组件中监听 CounterComponent 子组件的 change 事件,然后在 change 事件中更新 initialCount 的值。详细示例如下:
counter.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>子组件当前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input() count: number = 0; @Output() change: EventEmitter<number> = new EventEmitter<number>(); increment() { this.count++; this.change.emit(this.count); } decrement() { this.count--; this.change.emit(this.count); } }
app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <p>父组件当前值:{{ initialCount }}</p> <exe-counter [count]="initialCount" (change)="initialCount = $event"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; }
其实双向绑定是由两个单向绑定组成:
模型 -> 视图数据绑定
视图 -> 模型事件绑定
Angular 中 [] 实现了模型到视图的数据绑定,() 实现了视图到模型的事件绑定。把它们两个结合在一起 [()] 就实现了双向绑定。也被称为 banana in the box 语法。
[()] 语法示例
counter.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>子组件当前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input() count: number = 0; // 输出属性名称变动: change -> countChange @Output() countChange: EventEmitter<number> = new EventEmitter<number>(); ... // 其余代码未改动 }
app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <p>父组件当前值:{{ initialCount }}</p> <exe-counter [(count)]="initialCount"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; }
从上面可以看出,[(modelName)] 可以拆分成两部分 modelName 和 modelNameChange ,[modelName] 用于绑定输入属性,(modelNameChange) 用于绑定输出属性。当 Angular 在解析模板时,碰到 [(modelName)] 情势的绑定语法,它会等待这个指令中会存在一个名为 modelName 的输入属性和一个名为 modelNameChange 的输出属性。
ngModel
使用过 Angular 1.x 的读者,应当很熟知 ng-model 这个指令,我们通过它来实现数据的双向绑定。那么在 Angular 中有对应的指令么 ?答案是有滴,它就是 ngModel 指令。
ngModel双向绑定示例
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <p>你输入的会员名是:{{ username }}</p> <input type="text" [(ngModel)]="username" /> ` }) export class AppComponent { username: string = ''; }
ngModel表单验证示例
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', styles:[ `.error { border: 1px solid red;}` ], template: ` <p>你输入的会员名是:{{ username }}</p> <input type="text" [(ngModel)]="username" #nameModel="ngModel" [ngClass]="{error: nameModel.invalid}" required/> {{nameModel.errors | json}} ` }) export class AppComponent { username: string = ''; }
以上示例利用 @Directive 指令 metadata 信息中的 exportAs 属性,猎取 ngModel 实例,停止猎取控件的状态,控件状态分类如下:
valid - 表单值有效
pristine - 表单值未改动
dirty - 表单值已改动
touched - 表单已被拜访过
untouched - 表单未被拜访过
以上就是Angular中Input和Output的介绍(附代码)的具体内容,更多请关注百分百源码网其它相关文章!