Angular4 開發(fā)實(shí)戰(zhàn):(6) 創(chuàng)建指令(Directive)

2018-06-19 11:24 更新
指令(Directive)也是我們?cè)陂_發(fā)中常用的。

創(chuàng)建指令 我們創(chuàng)建一個(gè)button指令:

ng g directive button

對(duì)于指令,會(huì)生成兩個(gè)文件:

button.directive.ts  

button.directive.spec.ts


基礎(chǔ)模板如下:

// button.directive.ts   

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


@Directive({   

  selector: '[appButton]'  

})  

export class ButtonDirective {    

  constructor() { }   

}

對(duì)于指令,selector一般使用方括號(hào)屬性方式,如上。

使用方法:

<button appButton>指令按鈕</button>

指令有兩種:
  • 屬性型指令:修改宿主元素的樣式或行為等
  • 結(jié)構(gòu)型指令,比如`*ngIf`,`*ngFor`:修改DOM結(jié)構(gòu)。
屬性型指令 上面的button指令還沒(méi)有什么作用,下面讓我們來(lái)修改一下,先往style.css中添加下列樣式:

button.btn {   

  padding: 10px;   

  background: blue;   

  color: #fff;   

  border-radius: 4px;   

  border: none;  

}

修改button.directive.ts

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


@Directive({   

  selector: '[appButton]'  

})  

export class ButtonDirective implements AfterViewInit{    

  constructor(private er: ElementRef, private renderer2: Renderer2) { }    

  

  ngAfterViewInit() {   

    this.renderer2.addClass(this.er.nativeElement, 'btn');   

  }  

}

在上面的代碼中,我們將ElementRefRenderer2注入構(gòu)造函數(shù),前者會(huì)得到添加了appButton屬性的元素,后者是Angular提供的DOM API操作。 注:ElementRef和Renderer2后續(xù)會(huì)詳解。 然后在demo-directive.component.html中添加:

<button appButton>指令按鈕/button>

當(dāng)你打開網(wǎng)頁(yè)時(shí),會(huì)發(fā)現(xiàn)此button添加上了btn樣式類(背景色變藍(lán),字體顏色變白色)。 當(dāng)然,還有一些快捷的方式來(lái)給使用了指令的宿主元素添加屬性和事件: (1) @HostBinding() 再來(lái)修改一下button.directive.ts

export class ButtonDirective {        

  @HostBinding('style.font-size') fontSize = '20px';    

  ...  

}

當(dāng)你添加了上面的代碼時(shí),你會(huì)發(fā)現(xiàn)demo-directive.component.html中的按鈕字體變大了。 注:@HostBinding()里是的屬性和直接屬性綁定是一樣的效果,主要給宿主元素設(shè)置屬性。 (2) @HostListener 我們還可以為宿主元素綁定事件:

// button.directive.ts   

@HostListener('click') onClick() {

  alert('你點(diǎn)了我!');   

}

添加如上代碼后,你可以試試點(diǎn)擊按鈕。 注:@HostListener()里是事件名稱,后面跟著一個(gè)監(jiān)聽(tīng)函數(shù),名稱可以是任意合法的字符。 有些時(shí)候我們需要給這個(gè)指令傳遞一些值,如何實(shí)現(xiàn)呢? 還記得前面《組件通訊(@Input和@Output)》一章中我們講過(guò)@Input()可以設(shè)置別名。 修改button.directive.ts

export class ButtonDirective implements AfterViewInit {  

  ...    

  @Input('appButton') name: string; // 定義別名   


  constructor(private er: ElementRef, private renderer2: Renderer2) { }    

  

  ngAfterViewInit() {   

    ...    

    if (this.name) {   

      const text = this.renderer2.createText(this.name);   

      this.renderer2.appendChild(this.er.nativeElement, text);   

    }   

  }  

}

通過(guò)@Input()定義與指令同名的輸入屬性,我們就可以給指令傳遞參數(shù)了:

// demo-directive.component.html

<button appButton="額外名稱">指令按鈕</button>

結(jié)構(gòu)型指令 最常用的內(nèi)置結(jié)構(gòu)型指令有ngIf, ngFor, ngSwitch(1) ngIfdemo-directive.component.html中添加:

<div>   

  <button (click)="isShow = !isShow">點(diǎn)擊試試</button>   

  <div *ngIf="isShow">ngIf結(jié)構(gòu)型指令</div>  

</div>

隨著點(diǎn)擊按鈕,isShow屬性值會(huì)在true和false之間切換,而div也會(huì)跟著顯示或隱藏,其實(shí)是插入或移除。 而在Angular4中,新增else效果(使用模板變量#name):

<button (click)="isShowElse = !isShowElse">點(diǎn)擊試試ngIf else</button>   

<div *ngIf="isShowElse else next">ngIf結(jié)構(gòu)型指令中的else</div>   

<ng-template #next>else效果</ng-template>

有些時(shí)候我們還可以這樣:

<ng-container *ngIf="isShow"></ng-container>

ng-container元素會(huì)將其里面的內(nèi)容插入或移除,但ng-container元素不會(huì)出現(xiàn)在頁(yè)面里。 (2) ngFor ngFor一般用來(lái)顯示數(shù)據(jù)列表:

// demo-directive.component.html   

<li *ngFor="let book of books">{{book}}</li>   


// demo-directive.component.ts    

this.books = ['HTML', 'Javascript'];

帶索引:

<h4>帶索引</h4>   

<ul>   

  <li *ngFor="let book of books; index as i">{{i + ':' + book}}</li>   

</ul>

(3) ngSwitch ngSwitch與JavaScript中的switch類似:

<div [ngSwitch]="animal">   

  <div *ngSwitchCase="'dog'">汪</div>   

  <div *ngSwitchCase="'cat'">喵</div>   

  <div *ngSwitchDefault>哼</div>   

</div>

自定義結(jié)構(gòu)型指令 我們可以創(chuàng)建自定義結(jié)構(gòu)型指令my-if.directive.ts

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


@Directive({   

  selector: '[appMyIf]'  

})  

export class MyIfDirective {    

  constructor(private templateRef: TemplateRef<any>,   

      private viewContainer: ViewContainerRef) { }    

   

  @Input() set appMyIf(condition: boolean) {   

    if (condition) {   

      this.viewContainer.createEmbeddedView(this.templateRef);   

    } else {   

      this.viewContainer.clear();   

    }   

  }  

}

在上面的代碼中,我們使用@Input()屬性裝飾器的setter方法來(lái)定義appMyIf方法,里面的condition參數(shù)就是其屬性值。 使用demo-directive.component.html

 <button (click)="isMyShow = !isMyShow">點(diǎn)擊試試</button>   

<div *appMyIf="isMyShow">自定義結(jié)構(gòu)型指令appMyIf</div>

在上面的代碼中,當(dāng)isMyShow變?yōu)閠rue時(shí),底部的內(nèi)容顯示出來(lái);當(dāng)為false時(shí),底部?jī)?nèi)容消失了。 如發(fā)現(xiàn)任何問(wèn)題或有好的建議,歡迎在下方評(píng)論留言。



以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)