【教程】(Angular)模版引用變數的魔法

而井不想說話發表於2018-12-25

【翻譯】【教程】模版引用變數的魔法

原文連結:blog.angulartraining.com/tutorial-th…
作者:Alain Chautard
譯者:而井

圖片描述

模版引用變數是個好東西,它允許Angular完成許多有用的事情。我經常稱這個功能為“井號語法”,因為在模版中它依賴一個簡單的井號來建立對一個元素(譯者注:元素包括HTML元素和元件元素)的引用:

<input #phone placeholder="phone number">
複製程式碼

上述的語法是如此的簡潔:它建立了一個指向input元素的引用,這個引用稍後可以在我的模版中使用。需要注意的是,這個(引用)變數的作用域是它所定義的整個HTML模版(的範圍)(譯者注:即在定義這個引用變數的HTML模版中都可以訪問這個變數)。

例如,這裡就是我如何用這個引用來獲取輸入框的值(的例子):

<!-- phone指向輸入框元素 --> 
<button (click)="callPhone(phone.value)">Call</button>
複製程式碼

注意那個phone(變數)指向了inputHTMLElement物件例項。所以phone(變數)持有了(相應)HTMLElement(例項物件)的任何屬性和方法,如id、name、innerHTML、value等。

上述是一種避免使用ngModel或其他資料繫結的好方法,(因為)這種方法在校驗方面上不需要寫太多程式碼。

在元件上也奏效嗎?

答案就是可以奏效!假設我們有HelloWorldComponent如下:

@Component({
  selector: 'app-hello',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
    </div>
  `
})
export class HelloComponent {

   name = 'Angular';
}
複製程式碼

現在按照如下程式碼,我們使用了“井號語法”得到了元件的引用:

<app-hello #helloComp></app-hello>
複製程式碼

它(模版引用變數)一個最好的地方就是我們可以獲取實際上的元件例項物件HelloWorldComponent。所以我們可以訪問這個元件的任何方法或屬性,即使他們(的許可權)是宣告為私有或保護的,多麼令人驚喜:

<app-hello #helloComp></app-hello>
<!-- 下面這個表示式將會顯示(文字)"Angular" -->
{{helloComp.name}}
複製程式碼

我們不僅可以通過這種語法來讀取一個元件的資料,而且也能修改它。

對指令也奏效嗎?

當然(可以),不過這裡需要進一步瞭解它(模版引用變數)。大部分的指令將會被作為(譯者注:HTML或元件標籤)的屬性來使用,這意味著我們無法在那裡真正應用“井號語法”,除非我們使用相同的語法進行扭轉:

<form (ngSubmit)="onSubmit(myForm)" #myForm="ngForm">
複製程式碼

在上面的例子裡,myForm是一個指向(應用於表單的)ngForm指令的引用。

現在如果你細看上面的HTML元素,你可能會想:“等一下,那裡並沒有ngForm指令!我沒有見過任何屬性叫ngForm的!”,你(如果)這樣想就對了。

答案就在ngForm指令的原始碼中:

@Directive({
  selector: 'form:not([ngNoForm]):not([formGroup]),ngForm,[ngForm]',
  ...
  exportAs: 'ngForm'
})
複製程式碼

看到那個指令的選擇器的了沒?它(指令)將應用於任何沒有ngNoFormformGroup屬性的form表單元素之上。因此,ngForm指令將自動應用於我的form元素之上。

第二個被注意到的趣事就是裝飾器中的exportAs屬性。它告訴Angular:“嘿,如果有人想用模版引用變數來指向這個指令,(那麼指令的)名字就叫做ngForm”。

現在我們已經知道它是如何運作的了。我們可以建立定製指令,並通過一個叫exportAs的來暴露該指令。

譯者附

為了方便大家理解模版引用變數對指令的操控,我把相關連結的核心演示程式碼附在本文最後面。

import {Component} from '@angular/core';
import {NgForm} from '@angular/forms';
 
@Component({
  selector: 'example-app',
  template: `
    <form #f="ngForm" (ngSubmit)="onSubmit(f)" novalidate>
      <input name="first" ngModel required #first="ngModel">
      <input name="last" ngModel>
      <button>Submit</button>
    </form>
    
    <p>First name value: {{ first.value }}</p>
    <p>First name valid: {{ first.valid }}</p>
    <p>Form value: {{ f.value | json }}</p>
    <p>Form valid: {{ f.valid }}</p>
  `,
})
export class SimpleFormComp {
  onSubmit(f: NgForm) {
    console.log(f.value); // { first: '', last: '' }
    console.log(f.valid); // false
  }
}
複製程式碼

相關文章