Angular10教程--2.3 雙向繫結
技術標籤:angular教程angulartypescript
Angular10教程--2.3 雙向繫結
前面我們瞭解了屬性繫結、事件繫結以及輸入和輸出的使用,是時候瞭解雙向綁定了。本節,我們將利用
@Input()
和@Output()
來了解下雙向繫結。
原文閱讀…
定義:雙向繫結為應用中的元件提供了一種共享資料的方式。使用雙向繫結繫結來偵聽事件並在父元件和子元件之間同步更新值。(其實,也就是對@Input()
跟@Output()
的一種簡化)
雙向繫結大致可以分成兩種型別:
一、普通元件的雙向繫結
這個型別的雙向繫結可以發生在任何元件任何DOM
元素上,下面我們通過一個例項來具體認識一下。
在src/app/components/
下面建立一個sizer
元件作為子元件:
// src/app/components/sizer/sizer.component.html
<div>
<button class="btn btn-danger" (click)="dec()" title="smaller">-</button>
<button class ="btn btn-primary" (click)="inc()" title="bigger">+</button>
<label [style.font-size.px]="size">FontSize: {{size}}px</label>
</div>
// src/app/components/sizer/sizer.component.ts
...
export class SizerComponent implements OnInit {
public size = 14;
// ...
dec() {
this.size++;
}
inc() {
this.size--;
}
}
頁面將是這樣,且按鈕功能實現:
但是,這並不是我們想要的結果,我們需要從父元件傳入size
,從而讓sizer
元件改變字型大小。並且,通過sizer元件的按鈕點選事件,將改變後的size
的值回傳給父元件。
接下來我們將使用前面的知識來改造程式碼(也就是雙向繫結的原理介紹):
// src/app/app.component.html
// 下面的$event就是子元件傳過來的值(必須是$event)
<app-sizer [size]="appFontSize" (onSizeChange)="appFontSize = $event"></app-sizer>
<div [style.font-size.px]="appFontSize">子元件修改後的FontSize: {{appFontSize}}</div>
// src/app/app.component.ts
...
export class AppComponent {
appFontSize = 14;
}
// src/app/components/sizer/sizer.component.ts
...
export class SizerComponent implements OnInit {
// 建立輸入屬性size,為number或字串型別
@Input() size: number | string;
// 建立自定義事件onSizeChange,需要一個number型別的引數
@Output() onSizeChange = new EventEmitter<number>();
....
dec() {
this.resize(-1);
}
inc() {
this.resize(1);
}
resize(step: number) {
// 設定字型大小為12~40之間的值
this.size = Math.min(40, Math.max(12, +this.size + step));
// 通過事件傳值
this.onSizeChange.emit(this.size);
}
}
同樣實現了我們想要的效果:
但是,這樣是不是太麻煩了一點呢?下面,我們的雙向繫結正式出場:
Angular 的雙向繫結語法是方括號和圓括號的組合 [()]。[] 進行屬性繫結,() 進行事件繫結。修改下面程式碼:
// src/app/app.component.html
<app-sizer [(size)]="appFontSize"></app-sizer>
<div [style.font-size.px]="appFontSize">子元件修改後的FontSize: {{appFontSize}}</div>
// src/app/components/sizer/sizer.component.ts
...
export class SizerComponent implements OnInit {
@Input() size: number | string;
// 修改事件名,********必須是:屬性名 + Change 形式*********
@Output() sizeChange = new EventEmitter<number>();
....
resize(step: number) {
this.size = Math.min(40, Math.max(12, +this.size + step));
this.sizeChange.emit(this.size);
}
}
會發現,功能沒有受影響。
二、表單中的雙向繫結[(ngModel)]
根據之前基本的雙向繫結知識,
[(ngModel)]
語法可拆解為:1.名為
ngModel
的輸入屬性2.名為
ngModelChange
的輸出屬性
單獨使用表單元素
首先需要引入FormsModule
這個內建模組:
// src/app/app.module.ts
import {FormsModule} from '@angular/forms';
...
@NgModule({
// ...
imports: [
// ...
FormsModule
],
// ...
})
元件中使用:
<!-- src/app/app.component.html -->
<input type="text" [(ngModel)]="iptVal">
<p>input value is {{iptVal}}</p>
上面這行程式碼相當於:
<input [value]="iptVal" (input)="iptVal = $event.target.value" />
這其實很簡單的,類似vue裡面的寫法。
在標籤中使用
將程式碼放入<form>
標籤內:
<!-- src/app/app.component.html -->
<form>
<input type="text" [(ngModel)]="iptVal2">
<p>form 中input value is {{iptVal2}}</p>
</form>
但是,我們會發現瀏覽器會報錯:
報錯意思說,在form
表單中使用ngModel
的話,我們需要給input
新增一個name
屬性或者設定[ngModelOptions]="{standalone: true}"
修改程式碼:
<!-- src/app/app.component.html -->
<form>
<input type="text" [(ngModel)]="iptVal2" name="appIput2">
<p>form 中input value is {{iptVal2}}</p>
</form>
或者:
<!-- src/app/app.component.html -->
<form>
<input type="text" [(ngModel)]="iptVal2" [ngModelOptions]="{standalone: true}">
<p>form 中input value is {{iptVal2}}</p>
</form
或者:
<!-- src/app/app.component.html -->
<form>
<input type="text" [(ngModel)]="iptVal2" [ngModelOptions]="{name: 'appIput2'}">
<p>form 中input value is {{iptVal2}}</p>
</form
在表單元素 中使用雙向繫結就是這麼簡單了,注意引入FormsModule
模組就行。
總結:
1、雙向繫結的原理其實就是@Input()
跟@Output()
結合使用,需要注意語法是[(屬性名)]=“父元件中一個屬性名”,先繫結輸入,再繫結輸出;
2、在form
表單中使用雙向繫結,應首先引入FormsModule
這個內建模組,然後在input
元素上新增name
。
歡迎關注我的公眾號,公眾號將第一時間更新angular教程: