Angular Attribute Directives 屬性指令示意圖

← INSIGHTS & PERSPECTIVES | 前端開發

Angular Attribute Directives 屬性指令完整教學:從 @Directive 到 @Input 參數傳遞

Angular Attribute Directive 屬性指令教學:用 @Directive、ElementRef、HostListener 建立自訂 highlight 指令,並透過 @Input 傳入參數,附完整程式碼範例與常見問題。

Angular 的 Directive 分為結構型(Structural)與屬性型(Attribute)兩種,這篇文章要介紹的是屬性型的 Directive。我會用一個「滑鼠移入就變色」的 highlight 指令,帶你從 `@Directive` 宣告、`ElementRef` 操作 DOM、`@HostListener` 監聽事件,一路做到用 `@Input` 從 template 傳參數進指令,所有程式碼都可以直接照著做。

本篇的範例請見:Attribute Directive example / download example

Angular 的三種 Directive 有什麼差別?

Angular 有三種 directive:

類型說明範例
元件(Component)包含 template 的 directive`@Component`
結構指令(Structural Directive)通過添加和刪除 DOM 元素來更改 DOM 佈局`ngFor`、`ngIf`
屬性指令(Attribute Directive)改變元素、組件或其他指令的外觀或行為`ngStyle`

如何建立一個簡單的屬性型 directive?

一個 directive 最少需要一個帶有 `@Directive` 宣告的檔案,告訴 angular 該如何識別這個 directive。這邊我會用一個 highlight 的 directive 範例來解說:當用戶將鼠標懸停在該元素上時,設置元素的背景色。你可以像這樣應用它:

```html

Highlight me!

```

而下面我會一步步創立這一個 directive。

首先,用 cli 創立一個新的 directive:

```bash

ng generate directive highlight

```

會看到 cli 自動建立了兩個新的檔案:

ng generate directive 產生的檔案

產生的 `src/app/highlight.directive.ts` 檔案的內容如下:

```js

import { Directive } from '@angular/core';

@Directive({

selector: '[appHighlight]'

})

export class HighlightDirective {

constructor() { }

}

```

當我們 import 了 Directive 後,就可以在檔案內使用 `@Directive` 來設定 directive 的 CSS attribute selector。方括弧 `[]` 可以讓它成為一個屬性選擇器。在這邊為什麼會取名為 `appHighlight` 而不是 `highlight`?是為了避免與現有的 html 指令衝突。建議最好在所有的 directive 前面加上前綴字,以方便識別這是哪邊來的屬性——如果沒有前綴字,很容易會發生難以識別的錯誤。

接著看 `src/app/highlight.directive.ts` 的內容:

```js

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

@Directive({

selector: '[appHighlight]'

})

export class HighlightDirective {

constructor(el: ElementRef) {

el.nativeElement.style.backgroundColor = 'yellow';

}

}

```

這邊可以看到在建構子的地方會傳入 ElementRef,並且使用 `el.nativeElement` 直接修改 DOM 元素的背景顏色。

怎麼讓 directive 回應滑鼠事件(HostListener)?

若希望 directive 能夠接收使用者事件,可以加載 `HostListener`,如下:

```js

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

@Directive({

selector: '[appHighlight]'

})

export class HighlightDirective {

constructor(private el: ElementRef) { }

@HostListener('mouseenter') onMouseEnter() {

this.highlight('yellow');

}

@HostListener('mouseleave') onMouseLeave() {

this.highlight(null);

}

private highlight(color: string) {

this.el.nativeElement.style.backgroundColor = color;

}

}

```

顯示的結果如下圖:

HostListener 高亮效果示範

當然,也可以通過標準的 JavaScript 來訪問 DOM,並手動添加事件監聽器。但這種方法至少有三個問題,是不被建議的:

  • 需正確的監聽到各種平台的事件
  • 當要 destroy 這個 directive 時要手動移除事件
  • 直接操作 DOM API 不是好的方式

如何把參數傳進 directive(@Input)?

首先要先 import 所需的 Input:

```js

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

```

然後宣告所要輸入的變數:

```js

@Input() highlightColor: string;

```

那麼在使用 directive 傳入參數的方式有下面幾種:

```html

Highlighted in yellow

Highlighted in orange

Highlight me!

```

下面這個範例是使用上面自製的 directive,讓使用者選擇 highlight 的顏色。

template 檔案內容如下:

```html

My First Attribute Directive

Pick a highlight color

<input type="radio" name="colors" (click)="color='lightgreen'">Green

<input type="radio" name="colors" (click)="color='yellow'">Yellow

<input type="radio" name="colors" (click)="color='cyan'">Cyan

Highlight me!

```

component 內容如下:

```js

export class AppComponent {

color: string;

}

```

最後結果如下圖:

使用者選擇顏色的 highlight 效果

延伸閱讀

常見問題

Q什麼是 Angular 的 Attribute Directive?

Attribute Directive 是用來改變元素、組件或其他指令「外觀或行為」的指令,例如內建的 `ngStyle`。它不像結構指令(`ngIf`、`ngFor`)會增刪 DOM 元素,而是附掛在既有元素上調整其樣式或行為。

Q為什麼 directive 的 selector 要加前綴字(如 appHighlight)?

因為 directive 的 selector 是 CSS attribute selector,若取太通用的名字(如 `highlight`)容易與現有 HTML 屬性或其他套件的指令衝突。加上前綴字可以清楚識別這個屬性來自哪個專案或函式庫,避免難以排查的錯誤。

Q為什麼不建議在 directive 裡直接用 JavaScript 操作 DOM?

直接操作原生 DOM API 有三個問題:需要自己正確監聽各平台的事件、directive 銷毀時要手動移除事件監聽器,而且繞過了 Angular 的機制,不利於維護。使用 `ElementRef` 搭配 `@HostListener` 讓 Angular 幫你處理這些細節。

Q@Input 在 directive 中怎麼使用?

在 directive 類別中用 `@Input() highlightColor: string;` 宣告輸入屬性,之後就能在 template 用 `highlightColor="yellow"`(靜態字串)或 `[highlightColor]="color"`(綁定運算式)傳值進去。若屬性名稱與 selector 相同,還可以簡寫成 `[appHighlight]="'orange'"`。

參考資料

最後更新

2026-08-28(原文發布於 2018-01-01,本文保留原始筆記內容並補上 GEO 結構。)

關於作者 {#author}

Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。

首次發布:2018-01-01