structural directives angular

angular structural directives

小馬 2019/12/06 16:10:30
1059

前言:

使用過angular,就一定知道在寫html的時候會用到的*ngIf、*ngFor..這些angular提供可以改變結構的指令,在製作html網頁的時候幫我們省了不少工,也讓我們的html程式碼變得更容易閱讀。這些方便的方法,並不只內建的*ng開頭的指令,也可以自訂自己的指令,幫助我們更容易完成。

指令作法:

現在我們來介紹自訂指令的作法,我們打算自製一個類似*ngFor這樣的指令,在一個新專案中做模擬使用。

1、建立我們的新指令所需的類別。

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

@Directive({
  selector: '[appNgLoop]'
})
export class NgLoopDirective {

  constructor() { }
  
}

* selector表示的就是待會我們的指令名稱。

2、直接去app.component.html中加入一個顯示的部分。

<div appNgLoop>Hello</div>

雖然我們將指令放了進去,但因為我們沒給他任何的功能,所以她沒有任何反應,如果我們加上星號"*",他更會直接告訴我們她不認識這個template屬性。

3、現在我們把用於指令所需的參數帶入我們的類別。

   constructor(private container: ViewContainerRef,
        private template: TemplateRef<any>,
    ) { }

* ViewContainerRef是一個特殊的容器,可以在裡面放一個或多個的畫面。

* TemplateRef<any>就是我們宿主元素中寫的模板資料,除了用*開頭指令,<ng-template></ng-template>之間的模板也可以

4、現在我們重編譯啟動app,我們會發現一個錯誤,template沒有被定義的錯誤。所以我們現在要來修正這個錯誤。

  ngOnInit(): void {
    this.container.createEmbeddedView(this.template);
  }

5、如果現在看一下我們的app,我們可以看到以foo為內容的div元素正在顯示。我們剛剛創建了一條指令,該指令將我們提供給它的元素作為模板呈現。現在我們繼續把它做成我們想要的樣子。

6、首先我們將類別繼承一個父類別,並加入指令的輸入功能,因為待會要做類似*ngFor的效果,所以當然是一個Array。

export class NgLoopDirective implements OnChanges {
    @Input() appNgLoopOf: Array<any>;

    constructor(private container: ViewContainerRef,
        private template: TemplateRef<any>,
    ) { }
}

* appNgLoopOf是我們待會對我們自創的指令輸入的資訊。

7、加入繼承之後,我們會發現多了紅字,沒關係,待會我們會加入一個預設的方法,現在我們先配合修改畫面,如下。

<div *appNgLoop="numbers">foo</div>

8、接著我們來處理剛剛的紅字,加入一個新的方法。

  ngOnChanges() {
    for (const input of this.appNgLoop) {
      this.container.createEmbeddedView(this.template);
    }
  }

9、現在,在我們的指令中,我們依靠OnChanges在每次輸入更改時呈現視圖。我們遍歷numbers的時候,為每個項目創建一個嵌入式的view。

10、接下來我們嘗試在模板中使用輸入值。首先我們更改html如下。

<div *appNgLoop="let nr of numbers; index as i">
  {{ nr }} - Foo
  Index: {{ i }}
</div>

11、接著更改我們在ngOnChanges的處理方法。

 ngOnChanges() {
    this.container.clear();

    for (const input of this.appNgLoopOf) {
      this.container.createEmbeddedView(this.template,  {
        $implicit: input,
        index: this.appNgLoopOf.indexOf(input),
       });
    }
  }

12、在app重新整理之後,我們看到。

小結:

上述方式並不困難,但對於開發時相當有幫助,可以讓寫出來的程式碼更簡單也更容易閱讀,相信大家透過本介紹都可以輕鬆掌握本方法。

小馬