Angular 向組件傳遞模板的兩種方法
最近在寫(xiě)一個(gè)日期選擇器組件,為了滿足將來(lái)可能出現(xiàn)的各種需求,所以需要能夠高度的自定義組件的樣式。為了達(dá)到這個(gè)目的,需要能夠在日期選擇器組件外控制每個(gè)日期格子內(nèi)要顯示的內(nèi)容,比如,標(biāo)上節(jié)假日之類的。這時(shí)候,組件的一部分模板就需要由調(diào)用方提供。
在 React 里面,這種需求挺簡(jiǎn)單的,只要實(shí)現(xiàn)一個(gè) date => Element 這樣的函數(shù)就好了,但是 Angular 模板是純粹的模板,需要使用一些專門(mén)的概念才能實(shí)現(xiàn)這個(gè)功能。
第一種方式 <ng-content>
<ng-content> 這個(gè)標(biāo)簽到本文撰寫(xiě)時(shí)為止,還沒(méi)有官方的文檔,甚至連占位符都沒(méi)有。但是這并不妨礙我們的使用,外國(guó)熱心網(wǎng)友已經(jīng)總結(jié)出了 <ng-content> 在現(xiàn)階段的特點(diǎn)與作用。
基本用法
<!-- Wrapper.Component.html --> <div> hello <ng-content></ng-content> </div>
假設(shè)我們有一個(gè)上述的組件,然后向下面這樣調(diào)用:
<wrapper> <span> World </span> </wrapper>
那么最終的渲染結(jié)果將會(huì)是這樣的:
<div> hello <span> World </span> </div>
看起來(lái)就是發(fā)生了很簡(jiǎn)單的替換,但是如果在 Wrapper 中出現(xiàn)了多個(gè) <ng-content> 會(huì)出現(xiàn)多個(gè) <span> World </span> 嗎?答案是不會(huì)的。<ng-content> 的本質(zhì)只是移動(dòng)元素,并不會(huì)去自動(dòng)的創(chuàng)建傳入的模板,所以就算用 ngFor 套住 <ng-content> 也不會(huì)出現(xiàn)很多個(gè) <span> World </span>。如果傳入的是自定義的組件,這些組件也只會(huì)被實(shí)例化一次。
進(jìn)階用法
當(dāng)然,如果 <ng-content> 的功能僅僅只是這樣就顯得太雞肋了,在使用 <ng-content> 的時(shí)候可以指定一個(gè)選擇器,這個(gè)選擇器可以捕獲相符的直接子元素。例如:
<!-- Wrapper.Component.html --> <div> hello <ng-content></ng-content> <hr/> <ng-content select="span"></ng-content> </div>
然后像下面這樣使用:
<wrapper> <span> World </span> 2333 </wrapper>
最終的渲染結(jié)果將會(huì)是這樣:
<div> hello 2333 <hr/> <span> World </span> </div>
除了設(shè)置 ng-content 標(biāo)簽的 select 屬性之外,還可以在子元素上使用 ngProjectAs 屬性,這個(gè)屬性可以讓這個(gè)元素被父元素中指定的 ng-content 所捕獲。舉個(gè)例子:
<wrapper> <div ngProjectAs="span"> World </div> 2333 </wrapper>
這次被傳入的模板變成了一個(gè) div,但是因?yàn)樵O(shè)置了 ngProjectAs,所以“World”會(huì)出現(xiàn)在分割線下方。
第二種方式 NgTemplateOutlet 指令
使用 ng-content 確實(shí)可以起到傳入模板的效果,但是卻有個(gè)很致命的問(wèn)題,就是無(wú)法傳遞數(shù)據(jù)到傳入的模板中。為了將數(shù)據(jù)傳遞到傳入的模板中,就需要使用到 NgTemplateOutlet 指令。
基本使用
這個(gè)指令可以用來(lái)在模板的指定位置實(shí)例化一個(gè) TemplateRef 對(duì)象,同時(shí),在實(shí)例化的過(guò)程中還可以傳入一個(gè)數(shù)據(jù)對(duì)象。而 TemplateRef 可以通過(guò) ng-template 標(biāo)簽來(lái)創(chuàng)建,舉個(gè)例子:
@Component({
selector: 'ng-template-outlet-example',
template: `
<ng-container *ngTemplateOutlet="name; context: myContext"></ng-container>
<ng-template #name let-name="data"><span>Hello {{name}}!</span></ng-template>
`
})
class NgTemplateOutletExample {
myContext = {data: 'World'};
}
ng-container 是一個(gè)虛擬的元素,在這個(gè)元素上我們使用了一個(gè) NgTemplateOutlet 指令,指定了要實(shí)例化下面的名為 name 的 ng-template。同時(shí)把 myContext 這個(gè)對(duì)象作為實(shí)例化的數(shù)據(jù)上下文傳入,所以最終就會(huì)顯示 “Hello World!”。值得注意的是在 ng-template 里面獲取傳輸?shù)臄?shù)據(jù)上下文的方式:let-variableName='key'。
進(jìn)階使用
接下來(lái)就要實(shí)現(xiàn)本文開(kāi)頭提到的需求了,在組件外部傳入模板。還是以上面的例子為例,因?yàn)槟0逍枰赏饨缱鳛樽觾?nèi)容傳入,所以需要我們手動(dòng)來(lái)捕獲模板,這里需要就需要使用 ContentChild:
@Component({
selector: 'wrapper',
template: `
<ng-container *ngTemplateOutlet="name; context: myContext"></ng-container>
`
})
class NgTemplateOutletExample {
@ContentChild(TemplateRef) name: TemplateRef<any>;
myContext = {data: 'World'};
}
就是這么簡(jiǎn)單的改動(dòng)就可以讓我們的組件從外界接受模板了,來(lái)試一試:
<wrapper>
<ng-template let-value="data">
<span>Hello {{value}}!</span>
</ng-template>
</wrapper>
總結(jié)
以上就是 Angular 中向組件傳遞模板的兩種方法,其中,使用 <ng-content> 標(biāo)簽可以更方便的控制傳入的模板在 DOM 中的位置,而 NgTemplateOutlet 可以向傳入的模板傳遞渲染數(shù)據(jù),兩者搭配使用可以起到很好的效果。
以上所述是小編給大家介紹的Angular 向組件傳遞模板的兩種方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
python爬取安居客二手房網(wǎng)站數(shù)據(jù)(實(shí)例講解)
下面小編就為大家?guī)?lái)一篇python爬取安居客二手房網(wǎng)站數(shù)據(jù)(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
給angular加上動(dòng)畫(huà)效遇到的問(wèn)題總結(jié)
本文給大家總結(jié)了一下在angular中給ng-repeat列表加上動(dòng)畫(huà)效果時(shí)所遇到的問(wèn)題及解決方法,推薦給大家,希望大家能夠喜歡。2016-02-02
Angular.js實(shí)現(xiàn)獲取驗(yàn)證碼倒計(jì)時(shí)60秒按鈕的簡(jiǎn)單方法
最近做項(xiàng)目的時(shí)候又遇到了驗(yàn)證碼倒計(jì)時(shí)的需求,發(fā)現(xiàn)這個(gè)功能還是挺實(shí)用的,所以就想著總結(jié)一下,下面這篇文章主要給大家介紹了關(guān)于利用Angular.js如何實(shí)現(xiàn)獲取驗(yàn)證碼倒計(jì)時(shí)按鈕的簡(jiǎn)單方法,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-10-10
詳解什么是@ngrx/store開(kāi)發(fā)包中的MemoizedSelector
這篇文章主要為大家介紹了@ngrx/store開(kāi)發(fā)包中的MemoizedSelector使用分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
AngularJS實(shí)踐之使用NgModelController進(jìn)行數(shù)據(jù)綁定
大家都知道AngularJS中的指令是其尤為復(fù)雜的一個(gè)部分,但是這也是其比較好玩的地方。這篇文章我們就來(lái)說(shuō)一說(shuō)如何在我們自定義的指令中,利用ngModel的controller來(lái)做雙向數(shù)據(jù)綁定,本文對(duì)大家學(xué)習(xí)AngularJS具有一定的參考借鑒價(jià)值,有需要的朋友們可以參考借鑒。2016-10-10
AngularJS路由實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)實(shí)例
這篇文章主要為大家詳細(xì)介紹了AngularJS路由實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)的實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
詳解AngularJS中$http緩存以及處理多個(gè)$http請(qǐng)求的方法
$http 是 AngularJS 中的一個(gè)核心服務(wù),用于讀取遠(yuǎn)程服務(wù)器的數(shù)據(jù),通過(guò)本文給大家介紹AngularJS中$http緩存以及處理多個(gè)$http請(qǐng)求的方法,希望的朋友一起學(xué)習(xí)吧2016-02-02

