該指令用於基於已有的 TemplateRef
對象,插入對應的內嵌視圖。在應用 NgTemplateOutlet 指令時,咱們能夠經過 [ngTemplateOutletContext]
屬性來設置 EmbeddedViewRef
的上下文對象。綁定的上下文應該是一個對象,此外可經過 let
語法來聲明綁定上下文對象屬性名。typescript
友情提示:若 let 語法未綁定任何屬性名,則上下文對象中
$implicit
屬性,對應的值將做爲默認值。segmentfault
<ng-container *ngTemplateOutlet="templateRefExp; context: contextExp"></ng-container>
@Component({ selector: 'ng-template-outlet-example', template: ` <ng-container *ngTemplateOutlet="greet"></ng-container> <hr> <ng-container *ngTemplateOutlet="eng; context: myContext"></ng-container> <hr> <ng-container *ngTemplateOutlet="svk; context: myContext"></ng-container> <hr> <ng-template #greet><span>Hello</span></ng-template> <ng-template #eng let-name><span>Hello {{name}}!</span></ng-template> <ng-template #svk let-person="localSk"><span>Ahoj {{person}}!</span></ng-template> ` }) class NgTemplateOutletExample { myContext = {$implicit: 'World', localSk: 'Svet'}; }
TemplateRef 實例用於表示模板對象。函數
ViewContainerRef 實例提供了 createEmbeddedView()
方法,該方法接收 TemplateRef
對象做爲參數,並將模板中的內容做爲容器 (comment 元素) 的兄弟元素,插入到頁面中。源碼分析
若想進一步瞭解 TemplateRef
和 ViewContainerRef
的相關內容,請參考如下文章:this
<ng-template>
<ng-template>
用於定義模板,使用 *
語法糖的結構指令,最終都會轉換爲 <ng-template>
模板指令,模板內的內容若是不進行處理,是不會在頁面中顯示。對象
<ng-container>
<ng-container>
是一個邏輯容器,可用於對節點進行分組,但不做爲 DOM 樹中的節點,它將被渲染爲 HTML中的 comment
元素,它可用於避免添加額外的元素來使用結構指令。ip
若想進一步瞭解 <ng-template>
與 <ng-container>
的區別,請參考 Angular 4.x 動態建立組件 文章中我有話說版塊。ci
@Directive({ selector: '[ngTemplateOutlet]' })
export class NgTemplateOutlet implements OnChanges { // 表示建立的內嵌視圖 private _viewRef: EmbeddedViewRef<any>; // 注入ViewContainerRef實例 constructor(private _viewContainerRef: ViewContainerRef) {} }
@Input() public ngTemplateOutletContext: Object; // 用於設定EmbeddedViewRef上下文 @Input() public ngTemplateOutlet: TemplateRef<any>; // 用於設定TemplateRef對象
export class NgTemplateOutlet implements OnChanges { ngOnChanges(changes: SimpleChanges) { // 若this._viewRef已存在,則先從視圖容器中對應的位置移除該視圖。 if (this._viewRef) { this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._viewRef)); } // 若this.ngTemplateOutlet輸入屬性有綁定TemplateRef對象,則基於設定的上下文對象建立內嵌視圖 if (this.ngTemplateOutlet) { this._viewRef = this._viewContainerRef.createEmbeddedView( this.ngTemplateOutlet, this.ngTemplateOutletContext); } } }
ngTemplateOutlet
指令的源碼相對比較簡單,若是讀者有興趣瞭解 createEmbeddedView()
方法的內部實現,能夠參考 Angular 4.x NgIf 文章中的相關內容。
另外須要注意的是使用 let
語法建立模板局部變量,若未設置綁定的值,則默認是上下文對象中 $implicit
屬性對應的值。爲何屬性名是 $implicit
呢?由於 Angular 不知道用戶會如何命名,因此定義了一個默認的屬性名。 即 let-name="$implicit"
與 let-name
是等價的。