選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
4 分鐘閱讀時間 (884 個字)

Angular #35 - Directives and Pipes[1]

shutterstock_198004562
  • Angular 有很多內建的 Directive 與 Pipe
    • 目前看過的 Directive 像是 *NgIf *NgFor
      • *NgIf 是有條件地長出 DOM
      • *NgFor 是依傳入的陣列動態長出 DOM
    • 目前看過的 Pipe 像是 CurrencyPipe, DatePipe
      • Pipe 是透過在 template 上針對屬性加上 | 符號,後面再接著 pipe 的名稱與可選的參數
    • 以上,都不會在這邊提,畢竟官方就有文件可以參考了,本系列將專注於如何自訂 Pipe 與 Directive,並說明為何需要自訂
      • Directive 被區分為兩種
        • 一種會針對元素屬性作修改
        • 另一種會修改 component 的行為
      • 為何會需要自定義?
        • 在 controller/template 增加額外的邏輯的話,的確是不需要自定義 Directive 或是 Pipe,但:
          • 重用減少:
            • 與其在每一個 component 都實作類似邏輯,不如抽出來共用
            • 減少程式足跡(也就是程式碼的總量),藉以提高效率及可讀性
          • 較易維護,高內聚的元件
            • 有時候在 component 寫太多邏輯會讓它很像垃圾場,堆滿了和元件不相干的程式碼
            • 透過 Directive 與 Pipe 可以使得 component 單純許多
          • 可測試性
            • 抽出可共用的部份,不論是 Directive/Pipe 本身,或是 component 測試度都提高了
            • 因為相對而言情境的排列組合變少了,且相依程度也較低
    • 先下載程式碼的基底
        git clone https://github.com/angular-in-action/stocks-enhanced
        cd stocks-enhanced
        git checkout start
  • Directive 有區分 StructuralAttribute 兩種類型,但不論是哪種,其建立的方式大致上相似,除了兩點以外:
    • Structural directives 主要的集點放在元素如何顯示(修改 DOM), 而 Attribute directives 主要針對元素的 properties 作處理
    • Structural directives 在使用上是不用星號的, e.g. [ngClass]="{ active: true } ", 但 Attribute directives 是需要的 e.g. *ngIf="dataLoaded"
  • 再來就建立一個 attribute directive 吧
    • 這個 Directive 主要針對 SummaryComponent 的顏色作處理
      • 以下的指令可以用來建立 directive
          ng g d directives/card-type
        • 就像建立 Component 一樣,CLI 真是好用
      • 接著實作 card-type.directive.ts 的內容
          import { Directive, ElementRef, Input, OnInit } from '@angular/core';
          @Directive({
            selector: '[cardType]'
          })
          export class CardTypeDirective implements OnInit {
            @Input() cardType: number = 0;
            @Input() increaseClass = 'increase';
            @Input() decreaseClass = 'decrease';
            constructor(private el: ElementRef) { }
            ngOnInit() {
              if (this.cardType) {
                if (this.cardType >= 0) {
                  this.el.nativeElement.classList.add(this.increaseClass);
                  this.el.nativeElement.classList.remove(this.decreaseClass);
                } else if (this.cardType <= 0) {
                  this.el.nativeElement.classList.add(this.decreaseClass);
                  this.el.nativeElement.classList.remove(this.increaseClass);
                } else {
                  this.el.nativeElement.classList.remove(this.increaseClass);
                  this.el.nativeElement.classList.remove(this.decreaseClass);
                }
              }
            }
          }
        • 其實跟建 Component 差不多
        • @Directive decorator 定義了selector,意思是 cardType 這個 Directive 可以當作 HTML element(或 Angular Component) 的 attribute
        • 建構子注入了一個 ElementRef, 是一個參考,指向的就是被掛的元素本身
        • 特別留意一下這個 Directive 雖然有一點客製化,不過它開的 3 個 input 是可以任意給定 2 個 CSS class 與 1 個區分種類的 number
      • 來調整一下 summary.component.html,如下:
          <div class="mdl-card stock-card mdl-shadow--2dp" [cardType]="stock.change" [@fadeIn]="'in'" style="width: 100%;">
        • 原本是用 ngClass 搭配 isPositive()isNegative() 兩個方法,這個部份調整成以自定義的 Directive cardType 綁定到 stock.change 的屬性值
        • 除了加上新的 Directive 之外,也用上了 fadeIn 這個動畫, 這在 SummaryComponent 的 decorator 中有定義,使用的方法就是 @ 加上 trigger 的名稱(in)
        • 自定義的 Directive 現在取代了原本用 NgClass 設定的條件,而且能接受更多樣的 input
  • 小結
    • 此篇建立了一個 Attribute Directive
      • 它可以用來改變 Element 的屬性
      • 以此篇的例子就是調整 css
      • 下一篇將針對既有的第三方 Component,以自行定義的 Directive 去改變它的屬性
Angular #36 - Directives and Pipes[2]
Angular #34 - 深入 Routing [7]

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2025/06/09, 週一

Captcha 圖像