hostDirectives

問題情境

假設我們想要在應用程式的多個元素上實現相同的行為(如記錄點擊事件),傳統方法會需要在每個元素上手動添加指令(Directive)。這種做法會使標記變得冗長,且難以維護。

建立基本的 Log 指令

首先,我們創建一個基本的 LogDirective,用來記錄元素的點擊事件:

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

@Directive({
  selector: '[appLog]',
  standalone: true,
  host: {
    '(click)': 'onLog()',
  },
})
export class LogDirective {
  private elementRef = inject(ElementRef);
  
  onLog() {
    console.log('CLICKED');
    console.log(this.elementRef.nativeElement);
  }
}

這個指令會:

  • 監聽元素的點擊事件

  • 在控制台輸出「CLICKED」訊息

  • 輸出被點擊元素的原生 DOM 節點

傳統使用方式

傳統上,我們需要在每個想要記錄的元素上添加 appLog 指令:

<main>
  <app-learning-resources appLog />
  <hr />
  <app-auth appLog/>
  <p appLog *appAuth="'admin'" class="protected-content admin">
    Only admins should see this!
  </p>
  <p *appAuth="'user'" class="protected-content unauthenticated">
    Regular users should see this!
  </p>
  <p *appAuth="'guest'" class="protected-content authenticated">
    Guest users should see this!
  </p>
</main>

同時,還需要在使用的組件中導入這個指令:

import { LogDirective } from './log.directive';

@Component({
  // ...
  imports: [LogDirective],
  // ...
})
export class SomeComponent {}

這種方式的缺點:

  • 需要在每個元素上重複添加相同的指令

  • HTML 變得冗長

  • 如果要更改行為,需要修改多個地方

使用 hostDirectives

Angular 提供了 hostDirectives 選項,讓我們能夠將指令與組件「合併」,這樣組件自身會自動應用指定的指令:

import { LogDirective } from '../log.directive';

@Component({
  selector: 'app-auth',
  standalone: true,
  imports: [],
  templateUrl: './auth.component.html',
  styleUrl: './auth.component.css',
  hostDirectives: [LogDirective],
})
export class AuthComponent {}

重要特性:

  1. 組件級別的應用:使用 hostDirectives 會將指令應用於組件本身的宿主元素,而不是組件內的所有元素。

  2. 簡化標記:不需要在 HTML 中添加額外的屬性指令。

  3. 集中管理:可以在組件定義中集中管理多個指令。

注意事項:

  • hostDirectives 應用的指令只影響組件的宿主元素(即 <app-auth> 標籤本身),而不會影響組件內部的所有元素。

  • 點擊組件內的子元素不會觸發 LogDirective,除非事件冒泡到宿主元素。

  • 如果需要在組件內的多個元素上應用相同的指令,仍然需要在各個元素上手動添加或使用其他策略。

高級用法:指令導出與輸入屬性

hostDirectives 還支持導出指令的屬性和方法,以及設置指令的輸入屬性:

@Component({
  // ...
  hostDirectives: [
    {
      directive: LogDirective,
      inputs: ['level', 'format'],
      outputs: ['logged']
    }
  ],
})
export class AuthComponent {}

這種方式允許:

  • 通過 inputs 配置指令的輸入屬性

  • 通過 outputs 暴露指令的輸出事件

總結

hostDirectives 是 Angular 提供的一種機制,用於將指令直接應用於組件的宿主元素,從而減少模板中的冗餘標記並提高代碼的可維護性。它特別適用於需要在多個組件上應用相同行為的場景,例如日誌記錄、權限控制或樣式增強等。

Last updated