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 頁(yè)面的上下文中顯示數(shù)據(jù)的各種方法。 組件類和模板,共同構(gòu)成了應(yīng)用數(shù)據(jù)的一個(gè)視圖。

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

另外,你可以使用指令來(lái)向模板中添加邏輯,指令告訴 Angular 在渲染頁(yè)面時(shí)要如何修改。

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

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

使用插值顯示組件屬性

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

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

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

然后,到 "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';
}

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

修改完的模板會(huì)使用雙花括號(hào)形式的插值來(lái)顯示這兩個(gè)模板屬性:

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

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

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

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

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

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

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

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

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

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

選擇模板來(lái)源

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

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

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

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

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

ng generate component hero -t

初始化

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

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


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

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

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

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

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

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 指令來(lái)顯示 heroes 列表中的每一項(xiàng)。

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>
`

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

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

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

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

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

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

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

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

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

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

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

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

ng generate class hero

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

Path:"src/app/hero.ts"

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

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

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

來(lái)看第一個(gè)參數(shù):

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

public id: number,

這個(gè)簡(jiǎn)寫語(yǔ)法做了很多:

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

  • 聲明了一個(gè)同名的公共屬性。

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

使用 Hero 類

導(dǎo)入了 Hero 類之后,組件的 heroes 屬性就可以返回一個(gè)類型化的Hero 對(duì)象數(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>
`

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

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

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

來(lái)改一下這個(gè)例子,如果多于三位英雄,顯示一條消息。

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

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

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

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

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

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

試一下。因?yàn)檫@個(gè)數(shù)組中有四個(gè)條目,所以消息應(yīng)該顯示出來(lái)。 回到 "app.component.ts",從英雄數(shù)組中刪除或注釋掉一個(gè)元素。 瀏覽器應(yīng)該自動(dòng)刷新,消息應(yīng)該會(huì)消失。

源代碼

  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)在您知道了如何使用:

  • 帶有雙花括號(hào)的插值 (interpolation) 來(lái)顯示一個(gè)組件屬性。

  • ngFor 顯示數(shù)組。

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

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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)