本文介紹了angular之ng-template模板加載,分享給大家,具體如下:
創(chuàng)新互聯(lián)公司2013年至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站建設(shè)、網(wǎng)站制作網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元黃南州做網(wǎng)站,已為上家服務(wù),為黃南州各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:13518219792
html5中的template
template標(biāo)簽的含義:HTML 元素是一種用于保存客戶端內(nèi)容的機(jī)制,該內(nèi)容在頁(yè)面加載時(shí)是不可見(jiàn)的,但可以在運(yùn)行時(shí)使用JavaScript進(jìn)行實(shí)例化,可以將一個(gè)模板視為正在被存儲(chǔ)以供隨后在文檔中使用的一個(gè)內(nèi)容片段。
屬性
此元素僅包含全局屬性和只讀的 content 屬性,通過(guò)content 可以讀取模板內(nèi)容,而且可以通過(guò)判斷 content 屬性是否存在來(lái)判斷瀏覽器是否支持 元素。
示例
html
UPC_Code | Product_Name |
js
// 通過(guò)檢查來(lái)測(cè)試瀏覽器是否支持HTML模板元素 // 用于保存模板元素的內(nèi)容屬性。 if ('content' in document.createElement('template')) { // 使用現(xiàn)有的HTML tbody實(shí)例化表和該行與模板 let t = document.querySelector('#productrow'), td = t.content.querySelectorAll("td"); td[0].textContent = "1235646565"; td[1].textContent = "Stuff"; // 克隆新行并將其插入表中 let tb = document.getElementsByTagName("tbody"); let clone = document.importNode(t.content, true); tb[0].appendChild(clone); // 創(chuàng)建一個(gè)新行 td[0].textContent = "0384928528"; td[1].textContent = "Acme Kidney Beans"; // 克隆新行并將其插入表中 let clone2 = document.importNode(t.content, true); tb[0].appendChild(clone2); } else { // 找到另一種方法來(lái)添加行到表,因?yàn)椴恢С諬TML模板元素。 }
代碼運(yùn)行后,結(jié)果將是一個(gè)包含(由 JavaScript 生成)兩個(gè)新行的 HTML 表格:
UPC_Code Product_Name 1235646565 Stuff 0384928528 Acme Kidney Beans
注釋掉 tb[0].appendChild(clone);和tb[0].appendChild(clone2);,運(yùn)行代碼,只會(huì)看到:
UPC_Code Product_Name
說(shuō)明template元素中的內(nèi)容如果不經(jīng)過(guò)處理,瀏覽器是不會(huì)渲染的。
angular中的ng-template
以ngIf為例:
通過(guò)閱讀ngIf源碼學(xué)習(xí)如何運(yùn)用
在使用ngIf 指令時(shí)我們并未發(fā)現(xiàn)ng-template的身影,這是因?yàn)?*"(星號(hào))語(yǔ)法糖的原因,這個(gè)簡(jiǎn)寫方法是一個(gè)微語(yǔ)法,而不是通常的模板表達(dá)式, Angular會(huì)解開(kāi)這個(gè)語(yǔ)法糖,變成一個(gè)
{{hero.name}}
會(huì)被解析為
` {{hero.name}}
看下ngIf源碼
import {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef} from '@angular/core'; @Directive({selector: '[ngIf]'}) export class NgIf { private _context: NgIfContext = new NgIfContext(); private _thenTemplateRef: TemplateRef|null = null; private _elseTemplateRef: TemplateRef |null = null; private _thenViewRef: EmbeddedViewRef |null = null; private _elseViewRef: EmbeddedViewRef |null = null; constructor(private _viewContainer: ViewContainerRef, templateRef: TemplateRef ) { this._thenTemplateRef = templateRef; } @Input() set ngIf(condition: any) { this._context.$implicit = this._context.ngIf = condition; this._updateView(); } @Input() set ngIfThen(templateRef: TemplateRef ) { this._thenTemplateRef = templateRef; this._thenViewRef = null; // clear previous view if any. this._updateView(); } @Input() set ngIfElse(templateRef: TemplateRef ) { this._elseTemplateRef = templateRef; this._elseViewRef = null; // clear previous view if any. this._updateView(); } private _updateView() { if (this._context.$implicit) { if (!this._thenViewRef) { this._viewContainer.clear(); this._elseViewRef = null; if (this._thenTemplateRef) { this._thenViewRef = this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context); } } } else { if (!this._elseViewRef) { this._viewContainer.clear(); this._thenViewRef = null; if (this._elseTemplateRef) { this._elseViewRef = this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context); } } } } } export class NgIfContext { public $implicit: any = null; public ngIf: any = null; }
ngIf的源碼并不難,它的核心就在于_updateView函數(shù),它主要通過(guò)ViewContainerRef的createEmbeddedView和clear方法來(lái)實(shí)現(xiàn)模板TemplateRef的呈現(xiàn)和清除(先不關(guān)注當(dāng)中的then和else等的具體實(shí)現(xiàn))。它使用TemplateRef取得
TemplateRef
TemplateRef 實(shí)例用于表示模板對(duì)象,TemplateRef 抽象類的定義如下:
abstract get elementRef(): ElementRef; abstract createEmbeddedView(context: C): EmbeddedViewRef; }
在指令中通過(guò)依賴注入TemplateRef可以直接拿到ng-tempalte的TemplateRef,但是在component組件中我們則需要使用viewChild
template test @ViewChild('tptest') tptest: TemplateRef;
ViewContainerRef
ViewContainerRef 實(shí)例提供了 createEmbeddedView() 方法,該方法接收 TemplateRef 對(duì)象作為參數(shù),并將模板中的內(nèi)容作為容器 (comment 元素) 的兄弟元素,插入到頁(yè)面中。
export abstract class ViewContainerRef { /*基于TemplateRef對(duì)象創(chuàng)建Embedded View(內(nèi)嵌視圖),然后根據(jù)`index`指定的值,插入到容器中。 如果沒(méi)有指定`index`的值,新創(chuàng)建的視圖將作為容器中的最后一個(gè)視圖插入。*/ abstract createEmbeddedView( templateRef: TemplateRef , //內(nèi)嵌視圖 context?: C, index?: number): // 創(chuàng)建上下文 EmbeddedViewRef ; }
createEmbeddedView:context
創(chuàng)建Template 自身 Context 的屬性,以ngFor為例:
查看ngFor Context源碼:
export class NgForOfContext{ constructor( public $implicit: T, public ngForOf: NgIterable , public index: number, public count: number) {} get first(): boolean { return this.index === 0; } get last(): boolean { return this.index === this.count - 1; } get even(): boolean { return this.index % 2 === 0; } get odd(): boolean { return !this.even; } }
({{i}}) {{hero.name}}解析后: ({{i}}) {{hero.name}}
從例子中可以看到,通過(guò)let-i let-odd可以獲取到Template的context,這是angular提供的一種語(yǔ)法。因?yàn)樵?Angular中是沒(méi)有作用域繼承的,所以在模版中無(wú)法隱式實(shí)現(xiàn)兩個(gè)無(wú)關(guān)數(shù)據(jù)源。一個(gè)簡(jiǎn)單的實(shí)現(xiàn)方案就是:一個(gè)顯式、一個(gè)隱式。由于ng-template tag 是寫在某個(gè) Component 的 template屬性中的,所以在 ng-template tag 之下的部分當(dāng)然能訪問(wèn)的也只有 Component 作為 Context 提供的屬性,從而保持行為的一致性,而如果需要訪問(wèn)到 Template 的 Context,我們就需要使用額外的引入語(yǔ)法。比如 let-i="index",就是把 Template Context 中的 index屬性引入到當(dāng)前的 Component Context 中并賦予別名 i,這樣,我們就能夠使用 i 這個(gè)標(biāo)識(shí)符來(lái)訪問(wèn)到 Template Context 中的屬性了,并且仍然保持了行為的一致性和作用域的獨(dú)立性。
模板輸入變量是這樣一種變量,你可以在單個(gè)實(shí)例的模板中引用它的值。 這個(gè)例子中有好幾個(gè)模板輸入變量:hero、i和odd。 它們都是用let作為前導(dǎo)關(guān)鍵字。
模板輸入變量和模板引用變量是不同的,無(wú)論是在語(yǔ)義上還是語(yǔ)法上。
我們使用let關(guān)鍵字(如let hero)在模板中聲明一個(gè)模板輸入變量。 這個(gè)變量的范圍被限制在所重復(fù)模板的單一實(shí)例上。
而聲明模板引用變量使用的是給變量名加#前綴的方式(#var)。 一個(gè)引用變量引用的是它所附著到的元素、組件或指令。它可以在整個(gè)模板任意位置**訪問(wèn)。
模板輸入變量和引用變量具有各自獨(dú)立的命名空間。let hero中的hero和#hero中的hero并不是同一個(gè)變量。
總結(jié):
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。