用戶輸入

版本:Angular 5.0.0-alpha

用戶的動作如:點擊鏈接、按下按鈕或者輸入文字,都會產生 DOM 事件务唐。本章解釋如何使用 Angular 事件綁定語法把這些事件綁定到事件處理器。

運行在線例子(查看源碼)。

綁定到用戶輸入事件

我們可以使用 Angular 事件綁定機制來響應任意 DOM 事件劝篷。許多 DOM 事件是由用戶輸入觸發(fā)的。綁定這些事件提供了一種獲取用戶輸入的方式民宿。

要綁定 DOM 事件娇妓,只要把 DOM 事件的名字包裹在圓括號中,然后用放在引號中的模板語句對它賦值就可以了活鹰。下面的例子展示了一個事件綁定哈恰,它實現(xiàn)了一個點擊事件處理器:

<button (click)="onClickMe()">Click me!</button>

等號左邊的(click)表示把按鈕的點擊事件作為綁定目標。等號右邊引號中的文本是模板語句志群,通過調用組件的onClickMe()方法來響應這個點擊事件着绷。

寫綁定時,必須要知道模板語句的執(zhí)行上下文赖舟。出現(xiàn)在模板語句中的每個標識符都屬于特定的上下文對象蓬戚。這個對象通常都是控制此模板的 Angular 組件。上面的例子中只顯示了一行 HTML宾抓,那段 HTML 片段屬于一個更大的組件:

// lib/src/click_me_component.dart (component)

@Component(
  selector: 'click-me',
  template: '''
    <button (click)="onClickMe()">Click me!</button>
    {{clickMessage}}
  ''',
)
class ClickMeComponent {
  String clickMessage = '';

  void onClickMe() => clickMessage = 'You are my hero!';
}

當用戶點擊按鈕時子漩,Angular 調用ClickMeComponentonClickMe()方法豫喧。

從 $event 對象獲取用戶輸入

DOM 事件可以攜帶可能對組件有用的信息。這一部分將展示如何綁定輸入框的 keyup 事件幢泼,在每個敲擊鍵盤時獲取用戶輸入紧显。

下面的代碼監(jiān)聽 keyup 事件,并將整個事件載荷 ($event) 傳遞給組件的事件處理器缕棵。

// lib/src/keyup_components.dart (v1 template)

template: '''
  <input (keyup)="onKey(\$event)"> // 注意前面的 \孵班,因為這是在dart文件中,如果是html則不需要
  <p>{{values}}</p>
'''

模板在 Dart 文件中招驴,需要在$前面加\篙程。如果模板是外部的 HTML 文件,則直接使用$event别厘。

當用戶按下并釋放一個按鍵時虱饿,觸發(fā)keyup事件,Angular 在$event變量提供一個相應的 DOM 事件對象触趴,上面的代碼將它作為參數(shù)傳遞給onKey()方法氮发。

class KeyUp1Component {
  String values = '';

  void onKey(dynamic event) {
    values += event.target.value + ' | ';
  }
}

$event對象的屬性取決于 DOM 事件的類型。例如冗懦,鼠標事件和輸入框編輯事件包含不同的信息爽冕。

所有標準 DOM 事件對象都有一個target屬性,引用觸發(fā)該事件的元素披蕉。在本例中颈畸,target<input> 元素event.target.value返回該元素的當前內容没讲。

每次調用后承冰,onKey()方法把輸入框的值和后面跟著的分隔符 (|) 添加到組件的values屬性。模板使用 Angular 的插值表達式{{...}}來顯示values屬性食零。

假設用戶輸入字母“abc”困乒,然后用退格鍵一個一個刪除它們。 用戶界面將顯示:

 a | ab | abc | ab | a | |

或者贰谣,你可以用event.key替代event.target.value娜搂,在這個例中,同樣的用戶輸入產生結果如下:

 a | b | c | Backspace | Backspace | Backspace |

event 的類型

上面的例子聲明的onKey() event參數(shù)是dynamic吱抚。盡管這樣簡化了代碼百宇,但使用更具體的類型可以揭露實事件對象的屬性并防止愚蠢的錯誤。

下面的例子秘豹,使用類型重寫了方法:

// lib/src/keyup_components.dart (v1 class)

class KeyUp1Component {
  String values = '';

  void onKey(KeyboardEvent event) {
    InputElement el = event.target;
    values += '${el.value}  | ';
  }
}

現(xiàn)在event聲明為KeyboardEvent類型携御,event.target聲明為一個擁有 value屬性的InputElement類型。使用這些類型,onKey()方法更加清晰的表達了它期望從模板得到什么啄刹,以及它是如何解析事件的涮坐。

傳入 $event 是不可靠的做法

類型化事件對象通過傳遞整個 DOM 事件到方法中,暴露了一個重要問題:組件和模板細節(jié)緊密的聯(lián)系起來誓军。組件不使用 web APIs袱讹,它就不能夠提取信息。這就違反了模板(用戶看到的)和組件(應用如何處理用戶數(shù)據(jù))之間關注點分離的原則昵时。

下面的部分將介紹如何用模板引用變量來解決這個問題捷雕。

從一個模板引用變量中獲得用戶輸入

還有另一種方法獲取用戶數(shù)據(jù):Angular 模板引用變量提供了從模塊中直接訪問元素的能力。在標識符前加上井號 (#) 就能聲明一個模板引用變量壹甥。

下面的例子使用了局部模板變量救巷,在一個超簡單的模板中實現(xiàn)按鍵反饋功能。

@Component(
  selector: 'loop-back',
  template: '''
    <input #box (keyup)="0">
    <p>{{box.value}}</p>
  ''',
)
class LoopBackComponent {}

<input> 元素上聲明的名為box的模板引用變量句柠,引用<input>元素本身征绸。代碼使用box變量來獲得輸入元素的value值,并通過插值表達式把它顯示在<p>標簽中俄占。

這個模板是完全自包含的。它沒有綁定到組件淆衷,組件也沒做任何事情缸榄。

在輸入框中輸入,就會看到每次按鍵時祝拯,顯示也隨之更新了甚带。

除非你綁定一個事件,否則這將完全無法工作佳头。
只有在應用做了些異步事件(如按鍵)鹰贵,Angular 才更新綁定(并最終影響到屏幕)。本例代碼將keyup事件綁定到了數(shù)字 0康嘉,這可能是最短的模板語句了碉输。雖然這個語句不做什么,但它滿足 Angular 的要求亭珍,所以 Angular 將更新屏幕敷钾。

從模板引用變量獲得輸入框比通過 $event 對象更加簡單。下面的代碼使用模板引用變量來獲得用戶輸入肄梨,重寫了之前keyup示例阻荒。

lib/src/keyup_components.dart (v2)

@Component(
  selector: 'key-up2',
  template: '''
    <input #box (keyup)="onKey(box.value)">
    <p>{{values}}</p>
  ''',
)
class KeyUp2Component {
  String values = '';
  void onKey(value) => values += '$value | ';
}

這個方法最漂亮的一點是:組件代碼從視圖中獲得了干凈的數(shù)據(jù)值。它不再需要$event的信息及其結構了众羡。

按鍵事件過濾(使用key.enter

(keyup)事件處理器監(jiān)聽每一次按鍵侨赡。有時只在意回車鍵,因為它標志著用戶結束輸入。解決這個問題的一種方法是檢查每個$event.keyCode羊壹,只有鍵值是回車鍵時才采取行動蓖宦。

更簡單的方法是:綁定到 Angular 的 keyup.enter 模擬事件。然后舶掖,只有當用戶敲回車鍵時球昨,Angular 才會調用事件處理器。

// lib/src/keyup_components.dart (v3)

@Component(
  selector: 'key-up3',
  template: '''
    <input #box (keyup.enter)="values=box.value">
    <p>{{values}}</p>
  ''',
)
class KeyUp3Component {
  String values = '';
}

下面展示了它是如何工作的眨攘。

失去焦點事件

在前面的例中主慰,如果用戶沒有先按回車鍵,而是移開了鼠標鲫售,點擊了頁面中其它地方共螺,輸入框的當前值就會丟失。只有當用戶按下了回車鍵后情竹,組件的values屬性才能更新藐不。

讓我們通過同時監(jiān)聽輸入框的回車鍵和失去焦點事件來修復這個問題。

// lib/src/keyup_components.dart (v4)

@Component(
  selector: 'key-up4',
  template: '''
    <input #box
      (keyup.enter)="values=box.value"
      (blur)="values=box.value">
    <p>{{values}}</p>
  ''',
)
class KeyUp4Component {
  String values = '';
}

把它們放在一起

上一章介紹了如何顯示數(shù)據(jù)秦效。本章展示了事件綁定方法雏蛮。

現(xiàn)在,在一個微型應用中一起使用它們阱州,應用能顯示一個英雄列表挑秉,并把新的英雄加到列表中。用戶可以通過輸入英雄名和點擊添加按鈕來添加英雄苔货。

下面就是“Little Tour of Heroes”組件犀概。

// lib/src/little_tour_component.dart (little-tour)

@Component(
  selector: 'little-tour',
  template: '''
    <input #newHero
      (keyup.enter)="addHero(newHero.value)"
      (blur)="addHero(newHero.value); newHero.value='' ">

    <button (click)="addHero(newHero.value)">Add</button>

    <ul><li *ngFor="let hero of heroes">{{hero}}</li></ul>
  ''',
  directives: [coreDirectives],
)
class LittleTourComponent {
  List<String> heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];

  void addHero(String newHero) {
    if (newHero == null || newHero.isEmpty) return;
    heroes.add(newHero);
  }
}

注意

  • 使用模板變量來引用元素newHero模板變量引用了<input>元素夜惭。你可以在<input>的任何兄弟或子級元素中引用newHero姻灶。
  • 傳遞數(shù)值,而非元素诈茧。獲取輸入框的值并將它傳遞給組件的 addHero()方法产喉,而不是傳遞 newHero
  • 保持模板語句簡單敢会。(blur)事件綁定了兩個語句镊叁。第一句調用addHero()方法。第二句newHero.value=''在添加新英雄到列表中后清空輸入框走触。

總結

你已經(jīng)看過了響應用戶輸入和操作的基礎原理晦譬。

這些方法對小規(guī)模演示很實用,但是在處理大量用戶輸入時互广,很容易變得累贅和笨拙敛腌。要在數(shù)據(jù)錄入字段和模型屬性之間傳遞數(shù)據(jù)卧土,雙向數(shù)據(jù)綁定是更加優(yōu)雅和簡潔的方式。下一章Forms解釋了如何用NgModel來進行雙向綁定像樊。

下一步

表單

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末尤莺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子生棍,更是在濱河造成了極大的恐慌颤霎,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涂滴,死亡現(xiàn)場離奇詭異友酱,居然都是意外死亡,警方通過查閱死者的電腦和手機柔纵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門缔杉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人搁料,你說我怎么就攤上這事或详。” “怎么了郭计?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵霸琴,是天一觀的道長。 經(jīng)常有香客問我昭伸,道長梧乘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任勋乾,我火速辦了婚禮,結果婚禮上嗡善,老公的妹妹穿的比我還像新娘辑莫。我一直安慰自己,他們只是感情好罩引,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布各吨。 她就那樣靜靜地躺著,像睡著了一般袁铐。 火紅的嫁衣襯著肌膚如雪揭蜒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天剔桨,我揣著相機與錄音屉更,去河邊找鬼。 笑死洒缀,一個胖子當著我的面吹牛瑰谜,可吹牛的內容都是我干的欺冀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼萨脑,長吁一口氣:“原來是場噩夢啊……” “哼隐轩!你這毒婦竟也來了?” 一聲冷哼從身側響起渤早,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤职车,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鹊杖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悴灵,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年仅淑,在試婚紗的時候發(fā)現(xiàn)自己被綠了称勋。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡涯竟,死狀恐怖赡鲜,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情庐船,我是刑警寧澤银酬,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站筐钟,受9級特大地震影響揩瞪,放射性物質發(fā)生泄漏。R本人自食惡果不足惜篓冲,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一李破、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧壹将,春花似錦嗤攻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至暴区,卻和暖如春闯团,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仙粱。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工房交, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伐割。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓涌萤,卻偏偏與公主長得像淹遵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子负溪,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內容

  • 用戶輸入觸發(fā) DOM 事件透揣。我們通過事件綁定來監(jiān)聽它們,把更新過的數(shù)據(jù)導入回我們的組件和 model 川抡。(1)綁定...
    趙然228閱讀 3,386評論 0 2
  • 學習資料來自 Angular.cn 與 Angular.io辐真。 模板語法 在線例子 在 Angular 中,組件扮...
    小鐳Ra閱讀 3,745評論 0 3
  • 最開始是看著mv聽這首歌的感覺風格很清新童心但是看了歌詞卻發(fā)現(xiàn)不是這樣的 情感中的困擾人生中的徘徊一年一年長大卻什...
    凜冽閱讀 354評論 0 1
  • 明天就要走了崖堤,今天晚上有點睡不著侍咱,真的舍不得爸媽,一個月竟不知不覺就這樣過去了密幔,哎楔脯,不該王者的,打了幾局胯甩,本來是要...
    孫少的日記閱讀 199評論 0 0
  • 這里有一座高塔昧廷,是所有的人都必須去攀登的。它至多不過有一百級偎箫。這座高塔是中空的木柬,如果一個人一旦達到它的頂端,就會掉...
    夜雨狂歌如夢閱讀 603評論 0 0