我們定義了一個component,如果我們希望透過程式改變component內的背景顏色,過程不免是在component上加入一些binding的方式來動態改變component的style或class。
如果又有下一個component也要改變背景顏色,那麼就得對另一個component再改一次程式,如果要調整的數量一多,會變得維護不方便,而Angular提供了使用者自定義directive的方法,可以加入在html element上或是component上,提供對element調整的效果。
要建立自己客製的Directive,可以透過angluar-cli:
ng g d DirectiveName
來建立Directive,
或是直接建立檔案
import { Directive} from '@angular/core'; @Directive({ selector: '[appMyCustom]' }) export class MyCustomDirective { constructor() {} }如果是手動建立檔案,要記得在app.module內的declarations內加入MyCustomDirective設定。
如果html上有一段簡單的html,我們加入自己定義的directive:
<p appMyCustom >Test Directive</p>
接著要寫一個可以調整<p> element的directive,有幾種方式可以使用,下列一一列出:
1. 透過ElementRef調整Element
在自己建立好之Directive上,於constructor可以傳入ElementRef物件:import { Directive, ElementRef, OnInit } from '@angular/core'; @Directive({ selector: '[appMyCustom]' }) export class MyCustomDirective implements OnInit { ngOnInit() { this.elementRef.nativeElement.style.backgroundColor = 'green'; } constructor(private elementRef: ElementRef) { } }
則constructor傳入的就是<p> element的reference,我們之後可以透過ElementRef直接對element做修改與調整,如上面程式就是直接修改了<p>的背景顏色,雖然最方便也最簡單,但一般比較不建議用這方式。
2. 使用Renderer
import { Directive, ElementRef, OnInit } from '@angular/core'; @Directive({ selector: '[appMyCustom]' }) export class MyCustomDirective implements OnInit { ngOnInit() { this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'blue'); } constructor(private elementRef: ElementRef, renderer: Renderer2) {} }第二種方式是透過Renderer2來調整element,於constructor內傳入,並且呼叫其提供的方式修改element,如程式上的setStyle,使用方式:
setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2) : void
即是把elementRef傳入,指定css屬性與值即可,使用起來更方便。
Renderer2相關使用方式可以參考官網:Angular:Renderer2
3. 使用HostBinding與HostListener
HostBinding與HostListener可以說就是在自己所建的directive內綁定了element的某個屬性/事件,這兩個類別可以從angular/core內匯入,直接從程式碼來看會比較ㄑㄧ:HostBinding是用來綁定element的屬性到一個變數上,下面程式碼就是將
的 style.backgroundColor綁定在backgroundColor變數上,讓這個style的值可以透過Angular的變數直接連動。
@HostBinding('style.backgroundColor') backgroundColor: string;
HostListener是用來監聽發生在element上的特定事件,像是滑鼠移入移出(mouseenter/ mouseleave),像是這類javascript的事件,可以透過HostListener來監聽,在element觸發特定事件時,同時執行Angular內的程式,用程式來看:
@HostListener('mouseenter') mouseover(event: Event) { this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'blue'); }
當滑鼠指標移入<p>的範圍內,就會執行mouseover的function,將<p>的背景顏色設為藍色,同樣的也可以再增加一個mouseleave的HostListener,在滑鼠移開後將<p>的背景顏色設回原本的顏色:
@HostListener('mouseleave') mouseleave(event: Event) { this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'transparent'); }
4. 讓Directive允許傳入設定參數
Angular的Directive允許使用者可以傳入一些參數作為Directive內使用,以剛剛的例子來看,在滑鼠移入時會變為藍色,不過使用的人可能會希望滑鼠移入時變為其他顏色,遇到這情況,我們可以透過類似component的attribute binding方式來做到,同樣透過Input的方式,允許定義的directive可以綁定某個屬性,並且可以傳入參數,來達到想要的調整效果:首先在自訂的directive內加入Input
@Input() hilightColor: string = 'blue'; //預設為藍色
接著在<p> element的地方就可以綁定hilightColor屬性:
<p appMyCustom [hilightColor]="'yellow'">Test Directive</p>
(要注意雙引號內一定要有單引號!)
這時候會把hilightColor設定為黃色,因此如果希望在mouseenter事件觸發時,改變<p>的背景為黃色,就可以稍微調整HostListener程式為以下即可:
@HostListener('mouseenter') mouseover(event: Event) { this.backgroundColor = this.hilightColor;}
同理也可以用同樣的方式設定mouseleave時<p>背景顏色的變化。
直得一提的是,這一段程式碼可以稍微再簡潔一些的寫法,可以從
<p appMyCustom [hilightColor]="'yellow'">Test Directive</p>
<p appMyCustom hilightColor="yellow">Test Directive</p>
另外,angular如何判斷在<p>內的hulight是屬於我們自訂的directive的還是<p>的呢?
如今我們自己定義了一個attribute - src 在directive內,結果我們用在以下情況:
<img appMyCustom src="Url">
並且在directive內加入
@Input() src: string = '';
img內有src屬性,同時我們的directive內也有src屬性,誰會吃到Url屬性呢?
實際測試出來的結果是,img與appMyCustom都會吃到src這個屬性的值,所以在這情況,img可以抓到圖片,同時appMyCustom也可以抓到src傳入的參數Url。
但基本上來說,Angular會先找自己定義的directive看有沒有這個屬性,接著再找native element,如果兩者都有,兩者都可以吃到傳入屬性的內容。
自訂directive大致上這樣,還有一個比較特別的structural directive,就記錄在下一篇了。
沒有留言:
張貼留言