做幾個簡單的範例來記錄ng-template. ng-container之間的差異
ng-template
單純只有<ng-template>不會顯示於畫面上。所以如果開發者沒有對 <ng-template> 進行額外處理(ex:[ngIf]. [ngFor]…),基本上就等於無用。
<ng-template>
<div>ng-template-1</div>
</ng-template>
<ng-template>如果有加上[ngIf][ngFor]等額外處理的話的話,其內容才會出會於畫面。
<ng-template [ngIf]="1==1">
<div>ng-template-2</div>
</ng-template>

上面的HTML,如果搭配建構型指令*ngIf的話,寫法如下。這種寫法等同於上面的寫法。<div *ngIf="condition">
是<ng-template [ngIf]="condition">
的語法糖。普遍都是會用建構型指令這種寫法的。
並且會把div稱為是<ng-template>的宿主元素。
<div *ngIf="1==1">ng-template-3</div>

<div class="hello-world" *ngIf="1==1"> => 宿主元素
Hello World~1
<div class="qq">QQQ~</div> => 內容元素
</div>
<!--convert element-->
<ng-template [ngIf]="1==1">
<div class="hello-world"> => 宿主元素
Hello World~1
<div class="qq">QQQ~</div> => 內容元素
</div>
</ng-template>
另外我們接著來看看,把第二種寫法的<ng-template>替換成<div>的話,結果會是怎樣。可以看到跟第二種用法差異在,外層又多的一個<div>。如果只是單純的顯示結果可能這兩種用法沒有任何差異,但如果div有套用到css樣式的話,可能就會有影響了,為了避免這種問題,所以有了<ng-container>這個東西。
<div *ngIf="1==1">
<div *ngIf="1==1">ng-template-2_2</div>
</div>

接下來看看如過ngIf的條件不成立的話,會發生什麼事。結果也是什麼都沒有
<div *ngIf="1!=1">
<div *ngIf="1==1">ng-template-4</div>
</div>

測試結果:


那這樣<ng-template>有什麼用途呢?如果我們在畫面上有一個區塊是網頁載入時先不顯示的,等到特定條件被觸發後再顯示出來,這時後就可以用到<ng-template>了,範例如下:
<div *ngIf="show; else notshow">
當 show = true 時,顯示這些內容
</div>
<ng-template #notshow>
當 show = false 時,顯示這些內容
</ng-template>
總結:
1.比較會出現寫結構性變化時,會使用到 <ng-template>
2.<ng-template>裡面的元素可以透過TemplateRef取得
ng-container
跟<ng-template>不一樣。<ng-container>不用加上[ngIf][ngFor]等額外處理的話,其宿主元素內容直接顯示於畫面。
<ng-container>
<div>ng-container-1</div>
</ng-container>

搭配建構型指令*ngIf也是可以的喔。
<ng-container *ngIf="1==1">
<div>ng-container-2</div>
</ng-container>

接下來看看如過ngIf的條件不成立的話,會發生什麼事。結果也是什麼都沒有
<ng-container *ngIf="1!=1">
<div>ng-container-2</div>
</ng-container>

<ng-template> & <ng-container>差異比較:
看到這邊可以發現,<ng-template>
跟<ng-container>
用法其實是沒差太多的。既然沒有差太多,就表示還是有差異之處,讓我們來看看差在哪裡。我們先用三種寫法來呈現ngFor效果。
<!-- 使用ng-template + ngFor -->
<ng-template ngFor let-data [ngForOf]="datas">
<div>hello angular - ng-template for {{data}}</div>
</ng-template>
<!-- 使用ng-container + ngFor -->
<ng-container *ngFor="let data of datas">
<div>hello angular - ng-container for {{data}}</div>
</ng-container>
<!-- 使用div + ngFor -->
<div *ngFor="let data of datas">
<div>hello angular - div for {{data}}</div>
</div>


ng-template ngFor
跟ng-container *ngFor
所呈現出來的HTML是一樣的,但因為ng-template不能使用建構型指令(*ngFor),寫法比較繁瑣,所以比較常使用的是ng-container *ngFor
。
而ng-container *ngFor
跟div *ngFor
的差別在於HTML的呈現,ng-container + ngFor
不會顯示出HTML Tag,但是div+ ngFor
則會顯示出實體div Tag,如果沒有div沒有套用css樣式的話,是沒有什麼影響。但是div如果有套用css樣式的話,多了一層div,前端畫面可能就會受到影響了。透過上面的測試應該有比較了解ng-container的用法了。
至於div *ngFor
則會顯示出實體div Tag的原因是,div *ngFor
其實是Angular的語法糖,實際上是用ng-template ngFor
去包裝的,前面介紹<ng-template>時有提到,只要<ng-template>有符合出現的條件(ex:[ngIf]. [ngFor]…),宿主元素就會顯示於Dom之中,所以顯示出的第一個div為宿主元素,接在在顯示第二個div(內容元素),所以會有兩個div,如前面所說,如果我們對div有套用css樣式的話,多了一層div,前端畫面可能就會受到影響了。
如果使用ng-container *ngFor
,就沒有宿主元素的問題,就不會多顯示出一個沒有用途的宿主元素div了。
總結:
1.常見的使用情境是不想要多寫不必要的 html ,例如 div、span 等,但又想要將一個區塊的 html 包起來處理,就會使用到 <ng-container>
ChatGPT:




Ref:
1.一文了解 ng-template, ng-content, ng-container, 和 *ngTemplateOutlet的区别
2.Angular - ng-template & ng-container
3.ngTemplate VS ngContainer