首頁 >web前端 >js教程 >Angular中Input和Output的介紹(附程式碼)

Angular中Input和Output的介紹(附程式碼)

不言
不言轉載
2019-03-13 13:51:243917瀏覽

這篇文章帶給大家的內容是關於Angular中Input和Output的介紹(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

Input 是屬性裝飾器,用來定義元件內的輸入屬性。在實際應用場合,我們主要用來實作父元件向子元件傳遞資料。 Angular 應用是由各式各樣的元件組成,當應用程式啟動時,Angular 會從根元件開始啟動,並解析整棵元件樹,資料由上而下流下下一層子元件。

@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 &#39;@angular/core&#39;;
@Component({
  selector: &#39;exe-app&#39;,
  template: `
   <exe-counter [count]="initialCount"></exe-counter>
  `
})
export class AppComponent {
  initialCount: number = 5;
}

@Input('bindingPropertyName')

Input 裝飾器支援一個可選的參數,用來指定元件綁定屬性的名稱。如果沒有指定,則預設使用 @Input 裝飾器,裝飾的屬性名稱。具體範例如下:

counter.component.ts

import { Component, Input } from &#39;@angular/core&#39;;
@Component({
    selector: &#39;exe-counter&#39;,
    template: `
      <p>当前值: {{ count }}</p>
      <button (click)="increment()"> + </button>
      <button (click)="decrement()"> - </button>
    `
})
export class CounterComponent {
    @Input(&#39;value&#39;) count: number = 0;
... // 其余代码未改变
}

app.component.ts

import { Component } from &#39;@angular/core&#39;;
@Component({
  selector: &#39;exe-app&#39;,
  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 &#39;@angular/core&#39;;
@Component({
    selector: &#39;exe-counter&#39;,
    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 &#39;@angular/core&#39;;
@Component({
    selector: &#39;exe-counter&#39;,
    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[&#39;count&#39;]);
    }
    increment() {
        this.count++;
    }
    decrement() {
        this.count--;
    }
}

上面範例中需要注意的是,當手動改變輸入屬性的值,是不會觸發 ngOnChanges 鉤子的。

Output 是屬性裝飾器,用來定義元件內的輸出屬性。前面我們介紹了 Input 裝飾器的作用,也了解了當應用啟動時,Angular 會從根組件開始啟動,並解析整棵組件樹,數據自上而下流下下一級子組件。而我們今天介紹的 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 &#39;@angular/core&#39;;
@Component({
    selector: &#39;exe-counter&#39;,
    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 &#39;@angular/core&#39;;
@Component({
  selector: &#39;exe-app&#39;,
  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 &#39;@angular/core&#39;;
@Component({
    selector: &#39;exe-counter&#39;,
    template: `
      <p>当前值: {{ count }}</p>
      <button (click)="increment()"> + </button>
      <button (click)="decrement()"> - </button>
    `
})
export class CounterComponent {
    @Input() count: number = 0;
    @Output(&#39;countChange&#39;) change: EventEmitter<number> = new EventEmitter<number>();
... // 其余代码未改变
}

app.component.ts


import { Component } from &#39;@angular/core&#39;;
@Component({
  selector: &#39;exe-app&#39;,
  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 &#39;@angular/core&#39;;
@Component({
    selector: &#39;exe-counter&#39;,
    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 &#39;@angular/core&#39;;
@Component({
  selector: &#39;exe-app&#39;,
  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 &#39;@angular/core&#39;;
@Component({
    selector: &#39;exe-counter&#39;,
    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 &#39;@angular/core&#39;;
@Component({
  selector: &#39;exe-app&#39;,
  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 &#39;@angular/core&#39;;
@Component({
  selector: &#39;exe-app&#39;,
  template: `
   <p>你输入的用户名是:{{ username }}</p> 
   <input type="text" [(ngModel)]="username" />
   `
})
export class AppComponent {
  username: string = &#39;&#39;;
}

ngModel表單驗證範例

import { Component } from &#39;@angular/core&#39;;
@Component({
  selector: &#39;exe-app&#39;,
  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 = &#39;&#39;;
}

以上範例利用@Directive 指令metadata 資訊中的exportAs 屬性,取得ngModel 實例,進行取得控制項的狀態,控制項狀態分類如下:

valid - 表單值有效

pristine - 表單值未改變

dirty - 表單值已改變

#touched -表單已被存取過

untouched - 表單未被造訪過

以上是Angular中Input和Output的介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:前端修仙之路semlinker。如有侵權,請聯絡admin@php.cn刪除