Angular9 顯示數(shù)據(jù)

2020-06-30 17:50 更新

在視圖中顯示數(shù)據(jù)

各種 Angular 組件構(gòu)成了應(yīng)用的數(shù)據(jù)結(jié)構(gòu)。 組件關(guān)聯(lián)到的 HTML 模板提供了在 Web 頁面的上下文中顯示數(shù)據(jù)的各種方法。 組件類和模板,共同構(gòu)成了應(yīng)用數(shù)據(jù)的一個視圖。

在頁面上把數(shù)據(jù)的值及其表現(xiàn)形式組合起來的過程,就叫做數(shù)據(jù)綁定。 通過將 HTML 模板中的各個控件綁定到組件類中的各種數(shù)據(jù)屬性,你就把數(shù)據(jù)展示給了用戶(并從該用戶收集數(shù)據(jù))。

另外,你可以使用指令來向模板中添加邏輯,指令告訴 Angular 在渲染頁面時要如何修改。

Angular 定義了一種模板語言,它擴(kuò)展了 HTML 標(biāo)記,其擴(kuò)展語法可以讓你定義各種各樣的數(shù)據(jù)綁定和邏輯指令。 當(dāng)渲染完此頁面之后,Angular 會解釋這種模板語法,來根據(jù)你的邏輯更新 HTML 和數(shù)據(jù)的當(dāng)前狀態(tài)。 在你讀完模板語法這章之前,本頁中的練習(xí)可以先讓你快速了解下這種模板語法的工作方式。

在這個示例中,你將創(chuàng)建一個帶有英雄列表的組件。 你會顯示出這些英雄的名字清單,某些情況下,還會在清單下方顯示一條消息。 最終的用戶界面是這樣的:

使用插值顯示組件屬性

要顯示組件的屬性,最簡單的方式就是通過插值 (interpolation) 來綁定屬性名。 要使用插值,就把屬性名包裹在雙花括號里放進(jìn)視圖模板,如 {{myHero}}。

使用 CLI 命令 ng new displaying-data 創(chuàng)建一個工作空間和一個名叫 displaying-data 的應(yīng)用。

刪除 "app.component.html" 文件,這個范例中不再需要它了。

然后,到 "app.component.ts" 文件中修改組件的模板和代碼。

修改完之后,它應(yīng)該是這樣的:

Path:"src/app/app.component.ts"

import { Component } from '@angular/core';


@Component({
  selector: 'app-root',
  template: `
    <h1>{{title}}</h1>
    <h2>My favorite hero is: {{myHero}}</h2>
    `
})
export class AppComponent {
  title = 'Tour of Heroes';
  myHero = 'Windstorm';
}

再把兩個屬性 titlemyHero 添加到之前空白的組件中。

修改完的模板會使用雙花括號形式的插值來顯示這兩個模板屬性:

Path:"src/app/app.component.ts (template)"

template: `
  <h1>{{title}}</h1>
  <h2>My favorite hero is: {{myHero}}</h2>
  `

模板是包在 ECMAScript 2015 反引號 (`) 中的一個多行字符串。 允許把一個字符串寫在多行上, 使 HTML 模板更容易閱讀。

Angular 自動從組件中提取 titlemyHero 屬性的值,并且把這些值插入瀏覽器中。當(dāng)這些屬性發(fā)生變化時,Angular 就會自動刷新顯示。

嚴(yán)格來說,“重新顯示”是在某些與視圖有關(guān)的異步事件之后發(fā)生的,例如,按鍵、定時器完成或?qū)?HTTP 請求的響應(yīng)。

注:
- 你沒有調(diào)用 new 來創(chuàng)建 AppComponent 類的實例,是 Angular 替你創(chuàng)建了它。那么它是如何創(chuàng)建的呢?
- @Component 裝飾器中指定的 CSS 選擇器 selector,它指定了一個叫 <app-root& 的元素。 該元素是 "index.html" 文件里的一個占位符。

Path:"src/index.html (body)"

<body>
  <app-root></app-root>
</body>

當(dāng)你通過 "main.ts" 中的 AppComponent 類啟動時,Angular 在 "index.html" 中查找一個 <app-root> 元素, 然后實例化一個 AppComponent,并將其渲染到 <app-root> 標(biāo)簽中。

運(yùn)行應(yīng)用。它應(yīng)該顯示出標(biāo)題和英雄名:

選擇模板來源

@Component 元數(shù)據(jù)告訴 Angular 要到哪里去找該組件的模板。 你有兩種方式存放組件的模板。

你可以使用 @Component 裝飾器的 template 屬性來定義內(nèi)聯(lián)模板。內(nèi)聯(lián)模板對于小型示例或測試很有用。

此外,你還可以把模板定義在單獨的 HTML 文件中,并且讓 @Component 裝飾器的 templateUrl 屬性指向該文件。這種配置方式通常用于所有比小型測試或示例更復(fù)雜的場景中,它也是生成新組件時的默認(rèn)值。

無論用哪種風(fēng)格,模板數(shù)據(jù)綁定在訪問組件屬性方面都是完全一樣的。 這里的應(yīng)用使用了內(nèi)聯(lián) HTML,是因為該模板很小,而且示例也很簡單,用不到外部 HTML 文件。

  • 默認(rèn)情況下,Angular CLI 命令 ng generate component 在生成組件時會帶有模板文件,你可以通過參數(shù)來覆蓋它:

ng generate component hero -t

初始化

下面的例子使用變量賦值來對組件進(jìn)行初始化。

export class AppComponent {
  title: string;
  myHero: string;


  constructor() {
    this.title = 'Tour of Heroes';
    this.myHero = 'Windstorm';
  }
}

你可以用構(gòu)造函數(shù)來代替這些屬性的聲明和初始化語句。

添加循環(huán)遍歷數(shù)據(jù)的邏輯

*ngFor 指令(Angular 預(yù)置)可以讓你循環(huán)遍歷數(shù)據(jù)。下面的例子使用該指令來顯示數(shù)組型屬性中的所有值。

要顯示一個英雄列表,先向組件中添加一個英雄名字?jǐn)?shù)組,然后把 myHero 重定義為數(shù)組中的第一個名字。

Path:"src/app/app.component.ts (class)"

export class AppComponent {
  title = 'Tour of Heroes';
  heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
  myHero = this.heroes[0];
}

接著,在模板中使用 Angular 的 ngFor 指令來顯示 heroes 列表中的每一項。

Path:"src/app/app.component.ts (template)"

template: `
  <h1>{{title}}</h1>
  <h2>My favorite hero is: {{myHero}}</h2>
  <p>Heroes:</p>
  <ul>
    <li *ngFor="let hero of heroes">
      {{ hero }}
    </li>
  </ul>
`

這個界面使用了由 <ul><li> 標(biāo)簽組成的無序列表。<li> 元素里的 *ngFor 是 Angular 的“迭代”指令。 它將 <li> 元素及其子級標(biāo)記為“迭代模板”:

Path:"src/app/app.component.ts (li)"

<li *ngFor="let hero of heroes">
  {{ hero }}
</li>

注:
- 不要忘記 *ngFor 中的前導(dǎo)星號 (*)。它是語法中不可或缺的一部分。

注意看 ngFor 雙引號表達(dá)式中的 hero,它是一個模板輸入變量。 更多模板輸入變量的信息,見模板語法中的 微語法 (microsyntax)。

Angular 為列表中的每個條目復(fù)制一個 <li> 元素,在每個迭代中,把 hero 變量設(shè)置為當(dāng)前條目(英雄)。 Angular 把 hero 變量作為雙花括號插值的上下文。

本例中,ngFor 用于顯示一個“數(shù)組”, 但 ngFor 可以為任何可迭代的 (iterable) 對象重復(fù)渲染條目。

現(xiàn)在,英雄們出現(xiàn)在了一個無序列表中。

為數(shù)據(jù)創(chuàng)建一個類

應(yīng)用代碼直接在組件內(nèi)部直接定義了數(shù)據(jù)。 作為演示還可以,但它顯然不是最佳實踐。

現(xiàn)在使用的是到了一個字符串?dāng)?shù)組的綁定。在真實的應(yīng)用中,大多是到一個對象數(shù)組的綁定。

要將此綁定轉(zhuǎn)換成使用對象,需要把這個英雄名字?jǐn)?shù)組變成 Hero 對象數(shù)組。但首先得有一個 Hero 類。

ng generate class hero

此命令創(chuàng)建了如下代碼:

Path:"src/app/hero.ts"

export class Hero {
  constructor(
    public id: number,
    public name: string) { }
}

你定義了一個類,具有一個構(gòu)造函數(shù)和兩個屬性:idname。

它可能看上去不像是有屬性的類,但它確實有,利用的是 TypeScript 提供的簡寫形式 —— 用構(gòu)造函數(shù)的參數(shù)直接定義屬性。

來看第一個參數(shù):

Path:"src/app/hero.ts (id)"

public id: number,

這個簡寫語法做了很多:

  • 聲明了一個構(gòu)造函數(shù)參數(shù)及其類型。

  • 聲明了一個同名的公共屬性。

  • 當(dāng)創(chuàng)建該類的一個實例時,把該屬性初始化為相應(yīng)的參數(shù)值。

使用 Hero 類

導(dǎo)入了 Hero 類之后,組件的 heroes 屬性就可以返回一個類型化的Hero 對象數(shù)組了。

Path:"src/app/app.component.ts (heroes)"

heroes = [
  new Hero(1, 'Windstorm'),
  new Hero(13, 'Bombasto'),
  new Hero(15, 'Magneta'),
  new Hero(20, 'Tornado')
];
myHero = this.heroes[0];

接著,修改模板。 現(xiàn)在它顯示的是英雄的 idname。 要修復(fù)它,只顯示英雄的 name 屬性就行了。

Path:"src/app/app.component.ts (template)"

template: `
  <h1>{{title}}</h1>
  <h2>My favorite hero is: {{myHero.name}}</h2>
  <p>Heroes:</p>
  <ul>
    <li *ngFor="let hero of heroes">
      {{ hero.name }}
    </li>
  </ul>
`

顯示上還和以前一樣,不過代碼更清晰了。

通過 NgIf 進(jìn)行條件顯示

有時,應(yīng)用需要只在特定情況下顯示視圖或視圖的一部分。

來改一下這個例子,如果多于三位英雄,顯示一條消息。

Angular 的 ngIf 指令會根據(jù)一個布爾條件來顯示或移除一個元素。 來看看實際效果,把下列語句加到模板的底部:

Path:"src/app/app.component.ts (message)"

<p *ngIf="heroes.length > 3">There are many heroes!</p>

雙引號內(nèi)的模板表達(dá)式 *ngIf="heroes.length > 3" 的外觀和行為與 TypeScript 非常相似。當(dāng)組件的英雄列表包含三個以上的條目時,Angular 會將這段話添加到 DOM 中,這條消息就顯示出來了。如果只有三個或更少的條目,Angular 就會省略該段落,也就不會顯示任何消息。

雙引號中的模板表達(dá)式 *ngIf="heros.length > 3",外觀和行為很象 TypeScript。 當(dāng)組件中的英雄列表有三個以上的條目時,Angular 就會把這個段落添加到 DOM 中,于是消息顯示了出來。 如果有三個或更少的條目,則 Angular 會省略這些段落,所以不顯示消息。

注:
- Angular 并不是在顯示和隱藏這條消息,它是在從 DOM 中添加和移除這個段落元素。 這會提高性能,特別是在一些大的項目中有條件地包含或排除一大堆帶著很多數(shù)據(jù)綁定的 HTML 時。

試一下。因為這個數(shù)組中有四個條目,所以消息應(yīng)該顯示出來。 回到 "app.component.ts",從英雄數(shù)組中刪除或注釋掉一個元素。 瀏覽器應(yīng)該自動刷新,消息應(yīng)該會消失。

源代碼

  1. Path:"src/app/app.component.ts"

    import { Component } from '@angular/core';


    import { Hero } from './hero';


    @Component({
      selector: 'app-root',
      template: `
      <h1>{{title}}</h1>
      <h2>My favorite hero is: {{myHero.name}}</h2>
      <p>Heroes:</p>
      <ul>
        <li *ngFor="let hero of heroes">
          {{ hero.name }}
          </li>
      </ul>
      <p *ngIf="heroes.length > 3">There are many heroes!</p>
    `
    })
    export class AppComponent {
      title = 'Tour of Heroes';
      heroes = [
        new Hero(1, 'Windstorm'),
        new Hero(13, 'Bombasto'),
        new Hero(15, 'Magneta'),
        new Hero(20, 'Tornado')
      ];
      myHero = this.heroes[0];
    }

  1. Path:"src/app/hero.ts"

    export class Hero {
      constructor(
        public id: number,
        public name: string) { }
    }

  1. Path:"src/app/app.module.ts"

    import { NgModule } from '@angular/core';
    import { BrowserModule }  from '@angular/platform-browser';


    import { AppComponent } from './app.component';


    @NgModule({
      imports: [
        BrowserModule
      ],
      declarations: [
        AppComponent
      ],
      bootstrap: [ AppComponent ]
    })
    export class AppModule { }

  1. Path:"main.ts"

    import { enableProdMode } from '@angular/core';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';


    import { AppModule } from './app/app.module';
    import { environment } from './environments/environment';


    if (environment.production) {
      enableProdMode();
    }


    platformBrowserDynamic().bootstrapModule(AppModule);

總結(jié)

現(xiàn)在您知道了如何使用:

  • 帶有雙花括號的插值 (interpolation) 來顯示一個組件屬性。

  • ngFor 顯示數(shù)組。

  • 用一個 TypeScript 類來為你的組件描述模型數(shù)據(jù)并顯示模型的屬性。

  • ngIf 根據(jù)一個布爾表達(dá)式有條件地顯示一段 HTML。
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號