Dieser Artikel bietet Ihnen eine Einführung in die Eingabe und Ausgabe in Angular (mit Code). Freunde in Not können darauf verweisen.
Input ist ein Eigenschaftsdekorator, der zum Definieren von Eingabeeigenschaften innerhalb einer Komponente verwendet wird. In praktischen Anwendungen verwenden wir es hauptsächlich, um Daten von übergeordneten Komponenten an untergeordnete Komponenten zu übertragen. Angular-Anwendungen bestehen aus verschiedenen Komponenten. Wenn die Anwendung gestartet wird, beginnt Angular mit der Stammkomponente und analysiert den gesamten Komponentenbaum, wobei die Daten von oben nach unten zur nächsten Ebene der Unterkomponenten fließen.
@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')
Der Input-Decorator unterstützt einen optionalen verwendeten Parameter um den Namen der Komponentenbindungseigenschaft anzugeben. Wenn nicht angegeben, wird standardmäßig der @Input-Dekorator und der dekorierte Eigenschaftsname verwendet. Konkrete Beispiele sind wie folgt:
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 und Getter werden verwendet einschränken Das Festlegen und Abrufen von Attributen bietet eine gewisse Kapselung des Lesens und Schreibens von Attributen, wodurch der Code bequemer und skalierbarer werden kann. Durch Setter und Getter kapseln wir die privaten Eigenschaften in der Klasse, um zu verhindern, dass externe Vorgänge die privaten Eigenschaften beeinflussen. Darüber hinaus können wir auch einige Geschäftslogiken durch Setter kapseln:
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
Wenn der Wert der Daten Wenn sich das Eingabeattribut ändert, ruft Angular aktiv die ngOnChanges-Methode auf. Es wird ein SimpleChanges-Objekt abgerufen, das die neuen und alten Werte der gebundenen Eigenschaften enthält. Es wird hauptsächlich zur Überwachung von Änderungen in den Komponenteneingabeeigenschaften verwendet. Konkrete Beispiele sind wie folgt:
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--; } }
Im obigen Beispiel ist zu beachten, dass der ngOnChanges-Hook nicht ausgelöst wird, wenn der Wert des Eingabeattributs manuell geändert wird.
Output ist ein Eigenschaftsdekorator, der zum Definieren von Ausgabeeigenschaften innerhalb einer Komponente verwendet wird. Zuvor haben wir die Rolle des Eingabedekorators vorgestellt und außerdem erfahren, dass Angular beim Start der Anwendung von der Stammkomponente aus startet und den gesamten Komponentenbaum analysiert, wobei die Daten von oben nach unten zur nächsten Ebene der Unterkomponenten fließen. Der Output-Dekorator, den wir heute vorgestellt haben, wird verwendet, um untergeordnete Komponenten zu implementieren, um Informationen in Form von Ereignissen an übergeordnete Komponenten zu übermitteln.
Bevor wir den Output-Eigenschaftsdekorator vorstellen, stellen wir zunächst den Helden hinter EventEmitter vor. Es wird verwendet, um benutzerdefinierte Ereignisse auszulösen:
let numberEmitter: EventEmitter<number> = new EventEmitter<number>(); numberEmitter.subscribe((value: number) => console.log(value)); numberEmitter.emit(10);
Das Anwendungsszenario von EventEmitter in Angular ist:
Der Unterbefehl erstellt eine EventEmitter-Instanz und exportiert sie als Ausgabeattribut. Die untergeordnete Anweisung ruft die Methode emit(payload) in der erstellten EventEmitter-Instanz auf, um ein Ereignis auszulösen. Die übergeordnete Anweisung lauscht über die Ereignisbindung (eventName) auf das Ereignis und ruft das Nutzlastobjekt über das $event-Objekt ab. Wenn es sich etwas abstrakt anfühlt, setzen wir es gleich in die Praxis um.
@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')
Der Ausgabedekorator unterstützt einen optionalen verwendeten Parameter um den Namen der Komponentenbindungseigenschaft anzugeben. Wenn nicht angegeben, wird standardmäßig der @Output-Dekorator und der dekorierte Eigenschaftsname verwendet. Konkrete Beispiele sind wie folgt:
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}`; } }
Zwei-Wege-Bindung
Bevor wir die bidirektionale Bindung einführen, sprechen wir zunächst über eine Anforderung: Wenn sich der Zählwert der CounterComponent-Unterkomponente ändert, muss der Wert von initialCount in der übergeordneten AppComponent-Komponente synchron aktualisiert werden. Durch das obige Beispiel wissen wir, dass wir das Änderungsereignis der CounterComponent-Unterkomponente in der übergeordneten AppComponent-Komponente abhören und dann den Wert von initialCount im Änderungsereignis aktualisieren können. Spezifische Beispiele sind wie folgt:
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; }
Tatsächlich besteht die bidirektionale Bindung aus zwei unidirektionalen Bindungen Bindung:
Model-> View-Datenbindung
View-> Model-Ereignisbindung
Angular [] implementiert die Modell-zu-View-Datenbindung, () implementiert View um die Ereignisbindung zu modellieren. Durch die Kombination der beiden [()] wird eine bidirektionale Bindung erreicht. Wird auch als Banana-in-the-Box-Syntax bezeichnet.
[()] Syntaxbeispiel
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; }
Wie aus dem Obigen ersichtlich ist, [( modelName)] kann in zwei Teile modelName und modelNameChange aufgeteilt werden, [modelName] wird zum Binden von Eingabeeigenschaften verwendet, (modelNameChange) wird zum Binden von Ausgabeeigenschaften verwendet. Wenn Angular beim Parsen einer Vorlage auf eine Bindungssyntax der Form [(modelName)] stößt, erwartet es, dass in dieser Direktive eine Eingabeeigenschaft namens modelName und eine Ausgabeeigenschaft namens modelNameChange vorhanden sind.
ngModel
Leser, die Angular 1.x verwendet haben, sollten mit der ng-model-Direktive vertraut sein, die wir verwenden, um eine bidirektionale Bindung von Daten zu erreichen. Gibt es also eine entsprechende Anleitung in Angular? Die Antwort lautet: Ja, es ist die ngModel-Direktive.
ngModel-Beispiel für bidirektionale Bindung
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <p>你输入的用户名是:{{ username }}</p> <input type="text" [(ngModel)]="username" /> ` }) export class AppComponent { username: string = ''; }
ngModel-Formularvalidierungsbeispiel
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 = ''; }
Das obige Beispiel verwendet das exportAs-Attribut in den Metadateninformationen der @Directive-Direktive, um das ngModel abzurufen Instanz erstellen und den Kontrollstatus erhalten, wird der Kontrollstatus wie folgt klassifiziert:
gültig – der Formularwert ist gültig
unverfälscht – der Formularwert hat sich nicht geändert
dirty – Der Formularwert hat sich geändert
berührt – Das Formular wurde besucht
unberührt – auf das Formular wurde nicht zugegriffen
Das obige ist der detaillierte Inhalt vonEinführung in die Eingabe und Ausgabe in Angular (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!