Angular2 之 結構型指令

Angular 有一個強力的模板引擎,它能讓你輕鬆維護元素的DOM樹結構。

Angular指令可分爲三種

  • 組件
  • 屬性型指令
  • 結構型指令

組件

組件其實就是一個帶模板的指令。是這三種指令中最常用的,我們會編寫大量的組件來構建application。

屬性型指令

屬性型指令會修改元素的外觀或者行爲。 e.g. NgStyle可以修改元素的好幾個樣式。

結構型指令

結構型指令通過添加和刪除 DOM 元素來改變DOM的佈局。

我們經常看到的內置的結構型指令有:ngIf、ngSwitch、ngFor。

下面我們着重介紹ngIf。

NgIf案例分析

該指令接受一個布爾值,並據此讓一整塊DOM樹出現或者消失。

注意:這裏是出現或者消失,並不是隱藏。

隱藏元素的利弊

  • 當我們隱藏元素時,組件的行爲還在繼續。
    它仍然附加子啊它所屬於的DOM元素上,它仍然在監聽事件。angular會繼續檢查哪些能影響數據綁定的變更。組件原本要做的哪些事情仍然在進行!它還是佔用着那麼多的資源。

  • 另外一方面,重新顯示這個組件會很快。
    組件以前的狀態被保留着,並隨時可以顯示。組件不用重新初始化,當然,該操作付出代價比較大!

移除元素組件


  • 把ngIf設置爲false,將會影響到組件的資源消耗。angular會從DOM中移除該元素,停止相關組件的變更檢測,把它從DOM事件中移除,並且銷燬組件。組件會被垃圾回收,並釋放內存。

  • 如果我們很快再次使用這個組件的時候,重建組件的代價是非常大的。
    當ngIf重新變成true的時候,angular會重新創建該組件及其子樹。angular會重新運行每個組件的初始化邏輯。

總結

基於上面的利弊分析,無論是我們在使用內置的指令還是使用自定的指令的時候,我們應該自己分析提添加、移除元素以及創建和銷燬組件的後果。

標籤

  • 在Angular應用之外,標籤的默認CSS屬性display是none。 它的內容存在於一個隱藏的文檔片段中。
  • 而在Angular應用中,Angular會移除
    標籤及其子元素。

我們可以通過把短語”Hip! Hip! Hooray!”中間的”hip”包在一個標籤中來驗證下這個效果。

<p>
  Hip!
</p>
<template>
  <p>
    Hip!
  </p>
</template>
<p>
  Hooray!
</p>

這時候顯示的內容是’Hip! Hooray!’,在Angular的控制下,DOM的效果是不同的。

template-in-out-of-a2.png

顯然,Angular把標籤及其內容替換成了一個空白

自定義指令

我們自頂一個類似ngIf的指令。

import { Directive, Input } from '@angular/core';
import { TemplateRef, ViewContainerRef } from '@angular/core';

/** 選中器[],是匹配頁面上的指令,可以有多個名稱,由於是自己的指令,所以沒有使用ng開頭 */
@Directive({ selector: '[myUnless]' })
export class UnlessDirective {
  /**
   * 我們需要訪問模板,並且還需要一個渲染器來渲染它的內容。
   * 我們通過TemplateRef來訪問模板。渲染器是ViewContainerRef。
   * 我們把它們都作爲私有變量注入到構造函數中。
   */
  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef
    ) { }

  /**
   * 如果條件爲假,我們就渲染模板,否則就清空元素內容。
   * 我們現在先把myUnless屬性定義成一個“只寫”屬性。
   */
  @Input() set myUnless(condition: boolean) {
    if (!condition) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
      this.viewContainer.clear();
    }
  }
}

幾個概念

星號(*)效果

這個星號是一種“語法糖”。它簡化了ngIf和ngFor —— 無論是寫還是讀。

  • ngIf
    接下來這兩個ngIf範例的效果完全相同,只是我們寫成了另一種風格:
<!-- Examples (A) and (B) are the same -->
<!-- (A) *ngIf paragraph -->
<p *ngIf="condition">
  Our heroes are true!
</p>

<!-- (B) [ngIf] with template -->
<template [ngIf]="condition">
  <p>
    Our heroes are true!
  </p>
</template>

要知道,Angular會把風格(A)寫成風格(B)。 它把段落及其內容移到了
標籤中。 它把指令移到了
標籤上,成爲該標籤的一個屬性綁定 —— 包裝在方括號中。 宿主組件的condition
屬性的布爾值決定該模板的內容是否應該被顯示。

  • ngFor

Angular把*ngFor轉換成一個類似的形式:

<!-- Examples (A) and (B) are the same -->

<!-- (A) *ngFor div -->
<div *ngFor="let hero of heroes">{{ hero }}</div>

<!-- (B) ngFor with template -->
<template ngFor let-hero [ngForOf]="heroes">
  <div>{{ hero }}</div>
</template>

寫在後面

GitHub上集大家之力搞了一個前端面試題的項目,裏面都是大家面試時所遇到的題以及一些學習資料,有興趣的話可以關注一下。如果你也有興趣加入我們的話,請在項目中留言。項目同時也可以在gitbook上查看。

InterviewLibrary-GitHub
InterviewLibrary-gitbook

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章