Angular學習(4)自定義指令

大喻喻發表於2019-05-10
  • 屬性型指令:改變一個元素的外觀或行為,例如NgStyle 指令可以同時修改元素的多個樣式。
  • 結構型指令:修改檢視的結構。例如NgFor 和 NgIf等。

angular 內建了很多指令,但是這篇筆記主要記錄如何自定義指令。

建立指令

  • 匯入 Directive 裝飾器(而不再是 Component), 指令帶有 @Directive 裝飾器。
  • 匯入所需符號 Input、TemplateRef 和 ViewContainerRef, 任何結構型指令都會用到以上三個(屬性型常用:ElementRef、HostListener)。
  • 給指令類新增裝飾器。
  • 設定 CSS 屬性選擇器 ,以便在模板中標識出這個指令該應用於哪個元素。
// 建立指令的 CLI 命令
ng generate directive highlight
複製程式碼
import { Directive } from '@angular/core';

@Directive({
  // 定義一個 CSS 屬性型選擇器 [appHighlight], 通常帶字首(除ng),如app等,確保它們不會與標準 HTML 屬性衝突
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor() { }
}
複製程式碼

屬性型指令

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  // [appHighlight]定義了一個CSS 屬性選擇器
  // 屬性名應該拼寫成小駝峰形式,並且帶有一個字首,如app。這個字首不能用 ng,因為它只屬於 Angular 本身。
  selector: '[appHighlight]'
})
export class HighlightDirective {

  // ElementRef 通過其 nativeElement 屬性可以直接訪問宿主 DOM 元素
  constructor(private el: ElementRef) { }

  // @Input 的引數中把該選擇器highlightColor指定為別名appHighlight。
  @Input('appHighlight') highlightColor: string;

  // @HostListener 裝飾器訂閱某個屬性型指令所在的宿主 DOM 元素的事件
  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor || 'red');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}
複製程式碼
<p [appHighlight]="'orange'">Highlighted in orange</p>
複製程式碼

結構型指令

結構型指令中星號()被放在指令的屬性名之前, Angular 會把星號()語法解開成 <ng-template>

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

@Directive({ selector: '[appUnless]'})
export class UnlessDirective {
  private hasView = false;

  // 使用TemplateRef取得 <ng-template> 的內容,並通過ViewContainerRef來訪問這個檢視容器
  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef) { }

  // 沒有人會讀取 appUnless 屬性,因此它不需要定義 getter。
  @Input() set appUnless(condition: boolean) {
    if (!condition && !this.hasView) {
      this.viewContainer.createEmbeddedView(this.templateRef);
      this.hasView = true;
    } else if (condition && this.hasView) {
      this.viewContainer.clear();
      this.hasView = false;
    }
  }
}
複製程式碼
<p *appUnless="condition" class="unless a">1111</p>
複製程式碼

相關文章