What’s ngTemplateOutlet?
ngTemplateOutlet
is a directive that allows you to render a template dynamically.
Use Cases
一个大的页面,可能有一部分会多次被渲染,这种情况下,我们可以使用 ngTemplateOutlet
来减少重复的代码。
考虑如下需求:我们需要在一个页面上多次渲染某个产品信息,首先可以将产品信息的模板放在一个 ng-template
中,并给它起一个名字叫做product
, 然后通过 ngTemplateOutlet
来渲染。ngTemplateOutlet
接受一个模板变量作为参数,然后将这个模板变量所指向的模板渲染到当前的位置。
1 2 3 4 5 6 7 8 9
| <p>Product 1</p> <ng-container *ngTemplateOutlet="product"/> <p>Product 2</p> <ng-container *ngTemplateOutlet="product"/>
<ng-template #product> <p>Product name: computer</p> <p>Product price: 100$</p> </ng-template>
|
ngTemplateOutlet
还可以接受一个上下文参数,用来传递数据到模板中。比如上例中,我们可以把Product name和price进行参数化。
1 2 3 4 5 6 7 8 9
| <p>Product 1</p> <ng-container *ngTemplateOutlet="product; context: {name: 'computer', price: 100}"/> <p>Product 2</p> <ng-container *ngTemplateOutlet="product; context: {name: 'phone', price: 200}"/>
<ng-template #product let-name="name" let-price="price"> <p>Product name: {{ name }}</p> <p>Product price: {{ price }}$</p> </ng-template>
|
更进一步的,我们可以把name和price封装到一个对象中,然后传递这个对象。
1 2 3 4 5 6 7 8 9
| <p>Product 1</p> <ng-container *ngTemplateOutlet="product; context: {product: {name: 'computer', price: 100}}"/> <p>Product 2</p> <ng-container *ngTemplateOutlet="product; context: {product: {name: 'phone', price: 200}}"/>
<ng-template #product let-product="product"> <p>Product name: {{ product.name }}</p> <p>Product price: {{ product.price }}$</p> </ng-template>
|
渲染结果如下:
1 2 3 4 5 6 7
| Product 1 Product name: computer Product price: 100$
Product 2 Product name: phone Product price: 200$
|
再进一步,我们可以将product信息放到组件中,然后通过ngTemplateOutlet
来渲染。
1 2 3 4 5 6
| products = [ {name: 'Book 1', price: 100}, {name: 'Book 2', price: 200}, {name: 'Book 3', price: 300}, ]
|
1 2 3 4 5 6 7 8 9 10
| <p>Product 1</p> <ng-container *ngTemplateOutlet="product; context: {product: products[0]}"/> <p>Product 2</p> <ng-container *ngTemplateOutlet="product; context: {product: products[1]}"/>
<ng-template #product let-product="product"> <p>Product name: {{ product.name }}</p> <p>Product price: {{ product.price }}$</p> </ng-template>
|
再再进一步,我们可以用ngFor来循环渲染。
1 2 3 4 5 6 7 8
| <ng-container *ngFor="let product of products"> <ng-container *ngTemplateOutlet="productTemplate; context: {$implicit: product}"></ng-container> </ng-container>
<ng-template #productTemplate let-product> <p>Product name: {{ product.name }}</p> <p>Product price: {{ product.price }}$</p> </ng-template>
|
注意,这里使用了$implicit
, 这是一个特殊的关键字,表示默认的上下文参数。如果不指定上下文参数,$implicit
会被用作默认的上下文参数。也就是说,let-product="product"
可以简写为let-product
。而$implicit
后面的参数就是product. (注意,这句我已经看不懂了,有空重新整理一下。)
References
https://angular.dev/api/common/NgTemplateOutlet?tab=usage-notes