Directive 分為結構型和屬性型兩種,這一篇我要先介紹屬性型的 Directive(Attribute Directive)。我會用一個滑鼠懸停就改變背景色的高亮範例,一步步帶你建立自己的directive,最後再加上`@Input`讓使用者自訂高亮顏色。
Angular 的 directive 有哪三種?
Angular 有三種 directive:
- 元件(Component):包含template的directive。
- 結構指令(Structural Directive):通過添加和刪除DOM元素來更改DOM佈局(如`ngFor`、`ngIf`)。
- 屬性指令(Attribute Directive):改變元素、組件或其他指令的外觀或行為(如`ngStyle`)。
本篇的範例請見:Attribute Directive example / download example
怎麼建立一個簡單的屬性型 directive?
一個 directive 最少需要一個帶有`@Directive`宣告的檔案,告訴 angular 該如何識別這個 directive。
我會用一個 highlight 的 directive 範例來解說:當用戶將鼠標懸停在該元素上時,設置元素的背景色。你可以像這樣應用它:
```html
Highlight me!
```
接下來就一步步創立這個 directive。首先用 cli 創立一個新的 directive:
```bash
ng generate directive highlight
```
會看到 cli 自動建立了兩個新的檔案:

產生的`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 前面加上前綴字,以方便識別這是哪邊來的屬性——如果沒有前綴字,很容易發生難以識別的錯誤。
怎麼用 ElementRef 直接修改 DOM 樣式?
接著看`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`:
```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;
}
}
```
顯示的結果如下圖:

當然,也可以通過標準的 JavaScript 來訪問 DOM,並手動添加事件監聽器。但這種方法至少有三個問題,是不被建議的:
- 需正確的監聽到各種平台的事件
- 當要 destroy 這個 directive 時要手動移除事件
- 直接操作 DOM API 不是好的方式
怎麼輸入參數至 directive?
首先要先 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;
}
```
最後結果如下圖:

延伸閱讀
- Angular Attribute Directives 屬性指令完整教學:從 @Directive 到 @Input 參數傳遞:同樣聚焦 前端開發,可接著比較不同情境的做法。
- Angular Template Binding Syntax 教學:資料繫結的模版語法:同樣聚焦 Angular、前端開發,可接著比較不同情境的做法。
- Angular Lifecycle Hooks 教學:生命週期鉤子順序與使用時機:同樣聚焦 Angular、前端開發,可接著比較不同情境的做法。
常見問題
Attribute Directive 和 Structural Directive 有什麼差別?
Attribute Directive 負責改變元素的外觀或行為,例如`ngStyle`或自訂的高亮效果;Structural Directive 則是透過新增或移除 DOM 元素來改變版面結構,例如`ngIf`和`ngFor`。簡單說,前者改「樣子」,後者改「有沒有」。
為什麼 directive 的 selector 要加前綴字?
加上像`app`這樣的前綴字(如`appHighlight`)可以避免與現有 HTML 屬性或其他directive衝突,也能一眼看出這個屬性來自哪個應用程式,否則很容易發生難以識別的錯誤。
為什麼不直接用 JavaScript 操作 DOM 加事件監聽器?
手動監聽至少有三個問題:需要正確監聽各種平台的事件、directive 銷毀時要記得手動移除監聽器,而且直接操作 DOM API 本身就不是 Angular 建議的做法。用`@HostListener`可以讓 Angular 代管這些細節。
ElementRef 是什麼?
`ElementRef`是對宿主 DOM 元素的包裝,透過`el.nativeElement`可以拿到原生的 DOM 元素,進而直接修改它的樣式或屬性,例如範例中設定`backgroundColor`。
@Input() 在 directive 裡怎麼用?
在 directive 類別中用`@Input()`宣告屬性(如`highlightColor`)後,就能在 template 用靜態屬性`highlightColor="yellow"`、綁定字串`[highlightColor]="'orange'"`,或直接綁定到selector`[appHighlight]="'orange'"`三種方式傳值。
參考資料
最後更新
2026-08-28(原文發布於 2018-01-01,本文保留原始筆記內容並補上 GEO 結構。)
關於作者 {#author}
Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。
首次發布:2018-01-01
