Angular 4.x NgTemplateOutlet

NgTemplateOutlet 指令做用

該指令用於基於已有的 TemplateRef 對象,插入對應的內嵌視圖。在應用 NgTemplateOutlet 指令時,咱們能夠經過 [ngTemplateOutletContext] 屬性來設置 EmbeddedViewRef 的上下文對象。綁定的上下文應該是一個對象,此外可經過 let 語法來聲明綁定上下文對象屬性名。typescript

友情提示:若 let 語法未綁定任何屬性名,則上下文對象中 $implicit 屬性,對應的值將做爲默認值。segmentfault

NgTemplateOutlet 指令語法

<ng-container *ngTemplateOutlet="templateRefExp; context: contextExp"></ng-container>

NgTemplateOutlet 使用示例

@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

TemplateRef 實例用於表示模板對象。函數

ViewContainerRef

ViewContainerRef 實例提供了 createEmbeddedView() 方法,該方法接收 TemplateRef 對象做爲參數,並將模板中的內容做爲容器 (comment 元素) 的兄弟元素,插入到頁面中。源碼分析

若想進一步瞭解 TemplateRefViewContainerRef 的相關內容,請參考如下文章:this

<ng-template>

<ng-template> 用於定義模板,使用 * 語法糖的結構指令,最終都會轉換爲 <ng-template> 模板指令,模板內的內容若是不進行處理,是不會在頁面中顯示。對象

<ng-container>

<ng-container> 是一個邏輯容器,可用於對節點進行分組,但不做爲 DOM 樹中的節點,它將被渲染爲 HTML中的 comment 元素,它可用於避免添加額外的元素來使用結構指令。ip

若想進一步瞭解 <ng-template><ng-container> 的區別,請參考 Angular 4.x 動態建立組件 文章中我有話說版塊。ci

NgTemplateOutlet 源碼分析

NgTemplateOutlet 指令定義

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

NgTemplateOutlet 類私有屬性及構造函數

export class NgTemplateOutlet implements OnChanges {
  // 表示建立的內嵌視圖
  private _viewRef: EmbeddedViewRef<any>; 
  // 注入ViewContainerRef實例
  constructor(private _viewContainerRef: ViewContainerRef) {}
}

NgTemplateOutlet 類輸入屬性

@Input() public ngTemplateOutletContext: Object; // 用於設定EmbeddedViewRef上下文
@Input() public ngTemplateOutlet: TemplateRef<any>; // 用於設定TemplateRef對象

NgTemplateOutlet 指令聲明週期

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 是等價的。

相關文章
相關標籤/搜索