AngularJS 4(三)【指令】

風靈使發表於2018-08-24

指令概述

在 Angular 中有三種型別的指令:
1. 元件 — 擁有模板的指令。此類指令為最常用的指令。
2. 結構型指令 — 通過新增和移除 DOM 元素改變 DOM 佈局的指令。如 ngFor ngIf 等。
3. 屬性型指令 — 改變元素、元件或其它指令的外觀和行為的指令。如 ngStyle 等。

內建指令

指令使用時要在前頁加上 * 號。

ngIf

該指令主要作用於防範空指標錯誤,比如一個未定義的變數被當成物件使用時會報錯。

export class AppComponent {
}

<h1>{{currHero.name}}</h1>
上面將會丟擲錯誤,原因是 currHero 未定義。但加上指令 ngIf 則可以避免這種錯誤
<h1 *ngIf="currHero">{{currHero.a}}</h1>

該指令當表示式不為 false 時 DOM 元素不會存在 Document 中。

ngFor

export class AppComponent {
    data: Array<any> = [
        {name: 'Tom', age: 18},
        {name: 'Sam', age: 15},
        {name: 'Lucy', age: 28}
    ];
    getKeys(item){
        return Object.keys(item);
    }
}
<ul *ngFor='let obj of data">
    <li>{{obj.name}}</li>
</ul>
迴圈物件

*ngFor 指令預設不支援迴圈物件,所以如果需要迴圈的資料來源為物件時,可以使用 Object.keys(item) 的方法將物件的屬性轉換成陣列。

<ul *ngFor="let obj of data">
    <li *ngFor="let key of getKeys(obj)">{{key}}</li>
</ul>
模板輸入變數

ngFor 中可以通過 let 關鍵字建立了一個名叫 obj 的模版輸入變數。
<ul *ngFor="let obj of data; let idx = index">
模板變數:
- let idx = index
- let odd = odd
- let even = even
- let first = first
- let last = last

trackBy

ngFor指令有時候會效能較差,特別是在大型列表中。對一個條目的一丁點改動、移除或新增,都會導致級聯的 DOM 操作。

比如,當通過重新從伺服器來重新整理通訊錄,重新整理後的列表可能包含很多以前顯示過的聯絡人。但在 Angular 看來,它不知道哪些是以前就存在過的,只能清理舊列表、捨棄那些DOM元素,並用新的DOM元素來重建一個新列表。

解決這個問題,可以通過追蹤函式來避免這種折騰。追蹤函式會告訴 Angular 當重新獲取資料時,由於id沒有變,Angular 就不會去刪除原來的dom,只會更新其中的內容,不同的id再新增新的dom。效率就能提升了

trackByName(index, obj) {
    return obj.name;
}
<ul *ngFor="let obj of data; trackBy:trackByName">
    <span>{{obj.name}}</span>
</ul>

ngSwitch

<span [ngSwitch]="userName">
    <span *ngSwitchCase="'張三'">張三</span>
    <span *ngSwitchCase="'李四'">李四</span>
    <span *ngSwitchCase="'王五'">王五</span>
    <span *ngSwitchCase="'趙六'">趙六</span>
    <span *ngSwitchDefault>龍大</span>
</span>

自定義指令

  1. 新建一個 ts 檔案,highlight.directive.ts
  2. 編寫指令程式碼
import {Directive, ElementRef} from '@angular/core';

@Directive({
    selector: '[hl]'
})

export class HighlightDirective {
    constructor(el: ElementRef) {
        el.nativeElement.style.backgroundColor = 'yellow';
    }
}
  1. 在根模版 ./src/app.module.ts 中將指令新增到 declarations 陣列當中
import {HighlightDirective} from './directives/highlight.directive';
@NgModule({
    declarations: [HighlightDirective]
})
  1. 使用指令
<p hl>{{title}}</p>

自定義指令的事件監聽:HostListener

在指令中要對指令的宿主元素新增事件監聽需要用到 HostListener 屬性裝飾器
使用格式:HostListener([事件], [引數]) 事件

//['$event'] 對映到 btn
@HostListener('click', ['$event']) onclick(event) {
    console.log(event);
}

上面的事件只作用於當前指令的宿主元素,Angular 也可以監聽宿主元素外其它物件的事件。如 windowdocument 物件

//['$event'] 對映到 btn
@HostListener('document:click', ['$event']) onclick(event) {
    console.log(event.target);
}

除了用 HostListener 屬性裝飾器外也可以在指令配置資訊中設定:host: {'(document:click)': 'onClick($event)'}

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

@Directive({
    selector: '[hl]',
    host: {
        '(document:click)': 'onClick($event)'
    }    
})

export class HighlightDirective {
    constructor(el: ElementRef) {
        el.nativeElement.style.backgroundColor = 'yellow';
    }

    onClick(event){
        console.log(event.target);
    }    
}

自定義指令的動態屬性:HostBinding

可以在定義指令的時候動態給指令宿主新增屬性

@HostBinding('attr.role') role = 'admin';

也可以在指令配置資訊中設定

@Directive({
    selector: '[hl]',
    host: {
        'name': 'dk'
    }
})

獲取自定義指令的屬性值

<p hl="a" attr1="b" attr2="c">{{title}}</p>

要想獲得指令元素的屬性,要用到 @Input 裝飾器

export class HighlightDirective {
    @Input() hl: string;
    @Input() attr1: string;
    @Input() attr2: string;
    @Input() 
    set attr3(name: string){
        this._name = (name && name.trim()) || 'no name set';
    }
    get attr3(): string{
        return this._name;
    }

    constructor(el: ElementRef) {
        el.nativeElement.style.backgroundColor = 'yellow';
    }

    @HostListener('click', ['$event']) onclick(event) {
        console.log(this.hl, this.attr1, this.attr2);
    }
}

當然也可以對屬性給別名

export class HighlightDirective {
    @Input('hl') attr1: string;
    @Input('attr1') attr2: string;
    @Input('attr2') attr3: string;

    constructor(el: ElementRef) {
        el.nativeElement.style.backgroundColor = 'yellow';
    }

    @HostListener('click', ['$event']) onclick(event) {
        console.log(this.attr1, this.attr2, this.attr3);
    }
}

相關文章