ホームページ  >  記事  >  ウェブフロントエンド  >  Angular での入出力の概要 (コード付き)

Angular での入出力の概要 (コード付き)

不言
不言転載
2019-03-13 13:51:243804ブラウズ

この記事では、Angular での入出力の概要 (コード付き) を紹介します。これには一定の参考価値があります。必要な友人は参照してください。お役に立てば幸いです。

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 デコレーターが使用され、装飾されたプロパティ名が使用されます。具体的な例は次のとおりです。

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 を使用します。属性の設定と取得により、属性の読み取りと書き込みがカプセル化され、コードがより便利でスケーラブルになります。セッターとゲッターを通じて、クラス内のプライベート プロパティをカプセル化し、外部操作がプライベート プロパティに影響を与えるのを防ぎます。さらに、セッターを通じていくつかのビジネス ロジックをカプセル化することもできます。具体的な例は次のとおりです:

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

When the value of theデータ バインディングの入力属性が変更されると、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 は、コンポーネント内の出力プロパティを定義するために使用されるプロパティ デコレータです。前に入力デコレータの役割を紹介しました。また、アプリケーションが起動すると、Angular がルート コンポーネントから開始してコンポーネント ツリー全体を解析し、データが上から下に次のレベルのサブコンポーネントに流れることも学びました。今回紹介した出力デコレーターは、子コンポーネントを実装し、イベント形式で親コンポーネントに情報を通知するために使用されます。

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 オブジェクトを通じてペイロード オブジェクトを取得します。少し抽象的だと感じたら、すぐに実践してみましょう。

@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 デコレーターが使用され、装飾されたプロパティ名が使用されます。具体的な例は次のとおりです。

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 サブコンポーネントのカウント値が変更されると、AppComponent 親コンポーネントのinitialCount の値が同期的に更新される必要があります。上記の例を通じて、AppComponent 親コンポーネント内の CounterComponent サブコンポーネントの変更イベントをリッスンし、変更イベント内の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;
}

実際には、双方向バインディングは 2 つの一方向バインディングで構成されます。バインディング:

Model-> View データ バインディング

View-> モデル イベント バインディング

Angular [] はモデルからビューへのデータ バインディングを実装し、() は View を実装しますイベントバインディングをモデル化します。それら 2 つを組み合わせると [()] 双方向バインディングが実現します。ボックス構文のバナナとも呼ばれます。

[()] 構文例

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 の 2 つの部分に分割できます。[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 ディレクティブのメタデータ情報の exportAs 属性を使用して ngModel を取得しますインスタンスを作成してコントロールのステータスを取得すると、コントロールのステータスは次のように分類されます。

valid - フォーム値は有効です

pristine - フォーム値は変更されていません

dirty -フォームの値が変更されました

touched - フォームがアクセスされました

untouched - フォームはアクセスされていません

以上がAngular での入出力の概要 (コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事は前端修仙之路semlinkerで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。