W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
本主題描述如何使用內(nèi)容投影來創(chuàng)建靈活的可復(fù)用組件。
要查看或下載本主題中用到的示例代碼,請(qǐng)參見現(xiàn)場(chǎng)演練 / 下載范例 。
內(nèi)容投影是一種模式,你可以在其中插入或投影要在另一個(gè)組件中使用的內(nèi)容。例如,你可能有一個(gè) ?Card
?組件,它可以接受另一個(gè)組件提供的內(nèi)容。
以下各節(jié)介紹了 Angular 中內(nèi)容投影的常見實(shí)現(xiàn),包括:
內(nèi)容投影的最基本形式是單插槽內(nèi)容投影。單插槽內(nèi)容投影是指創(chuàng)建一個(gè)組件,你可以在其中投影一個(gè)組件。
要?jiǎng)?chuàng)建使用單插槽內(nèi)容投影的組件,請(qǐng)執(zhí)行以下操作:
<ng-content>
? 元素,讓你希望投影的內(nèi)容出現(xiàn)在其中。例如,以下組件使用 ?<ng-content>
? 元素來顯示消息。
import { Component } from '@angular/core';
@Component({
selector: 'app-zippy-basic',
template: `
<h2>Single-slot content projection</h2>
<ng-content></ng-content>
`
})
export class ZippyBasicComponent {}
有了 ?<ng-content>
? 元素,該組件的用戶現(xiàn)在可以將自己的消息投影到該組件中。例如:
<app-zippy-basic>
<p>Is content projection cool?</p>
</app-zippy-basic>
?
<ng-content>
? 元素是一個(gè)占位符,它不會(huì)創(chuàng)建真正的 DOM 元素。?<ng-content>
? 的那些自定義屬性將被忽略。
一個(gè)組件可以具有多個(gè)插槽。每個(gè)插槽可以指定一個(gè) CSS 選擇器,該選擇器會(huì)決定將哪些內(nèi)容放入該插槽。該模式稱為多插槽內(nèi)容投影。使用此模式,你必須指定希望投影內(nèi)容出現(xiàn)在的位置。你可以通過使用 ?<ng-content>
? 的 ?select
?屬性來完成此任務(wù)。
要?jiǎng)?chuàng)建使用多插槽內(nèi)容投影的組件,請(qǐng)執(zhí)行以下操作:
<ng-content>
? 元素,讓你希望投影的內(nèi)容出現(xiàn)在其中。select
?屬性添加到 ?<ng-content>
? 元素。 Angular 使用的選擇器支持標(biāo)簽名、屬性、CSS 類和? :not
? 偽類的任意組合。例如,以下組件會(huì)使用兩個(gè) ?<ng-content>
? 元素。
import { Component } from '@angular/core';
@Component({
selector: 'app-zippy-multislot',
template: `
<h2>Multi-slot content projection</h2>
Default:
<ng-content></ng-content>
Question:
<ng-content select="[question]"></ng-content>
`
})
export class ZippyMultislotComponent {}
使用 ?question
?屬性的內(nèi)容將投影到帶有 ?select=[question]
? 屬性的 ?<ng-content>
? 元素。
<app-zippy-multislot>
<p question>
Is content projection cool?
</p>
<p>Let's learn about content projection!</p>
</app-zippy-multislot>
不帶 SELECT 屬性的 NG-CONTENT
如果你的組件包含不帶 ?select
?屬性的 ?<ng-content>
? 元素,則該實(shí)例將接收所有與其他 ?<ng-content>
? 元素都不匹配的投影組件。
在前面的示例中,只有第二個(gè) ?<ng-content>
? 元素定義了 ?select
?屬性。結(jié)果,第一個(gè) ?<ng-content>
? 就會(huì)元素接收投影到組件中的任何其他內(nèi)容。
如果你的組件需要有條件地渲染內(nèi)容或多次渲染內(nèi)容,則應(yīng)配置該組件以接受一個(gè) ?<ng-template>
? 元素,其中包含要有條件渲染的內(nèi)容。
在這種情況下,不建議使用 ?<ng-content>
? 元素,因?yàn)橹灰M件的使用者提供了內(nèi)容,即使該組件從未定義 ?<ng-content>
? 元素或該 ?<ng-content>
? 元素位于 ?ngIf
?語句的內(nèi)部,該內(nèi)容也總會(huì)被初始化。
使用 ?<ng-template>
? 元素,你可以讓組件根據(jù)你想要的任何條件顯式渲染內(nèi)容,并可以進(jìn)行多次渲染。在顯式渲染 ?<ng-template>
? 元素之前,Angular 不會(huì)初始化該元素的內(nèi)容。
?<ng-template>
? 進(jìn)行條件內(nèi)容投影的典型實(shí)現(xiàn)。
<ng-template>
? 元素的組件中,使用 ?<ng-container>
? 元素渲染該模板,例如:<ng-container [ngTemplateOutlet]="content.templateRef"></ng-container>
本示例使用 ?ngTemplateOutlet
?指令來渲染給定的 ?<ng-template>
? 元素,你將在后續(xù)步驟中對(duì)其進(jìn)行定義。你可以將 ?ngTemplateOutlet
?指令應(yīng)用于任何類型的元素。本示例就將該指令分配給了 ?<ng-container>
? 元素,因?yàn)樵摻M件不需要渲染真實(shí)的 DOM 元素。
<ng-container>
? 元素包裝在另一個(gè)元素(例如 ?div
?元素)中,然后應(yīng)用條件邏輯。<div *ngIf="expanded" [id]="contentId">
<ng-container [ngTemplateOutlet]="content.templateRef"></ng-container>
</div>
<ng-template>
? 元素中,例如:<ng-template appExampleZippyContent>
It depends on what you do with it.
</ng-template>
這個(gè) ?<ng-template>
? 元素定義了一個(gè)組件可以根據(jù)其自身邏輯渲染的內(nèi)容塊。組件可以使用 ?@ContentChild
? 或 ?@ContentChildren
? 裝飾器獲得對(duì)此模板內(nèi)容的引用(即 ?TemplateRef
?)。前面的示例創(chuàng)建了一個(gè)自定義指令 ?appExampleZippyContent
?作為 API,以將 ?<ng-template>
? 標(biāo)記為組件內(nèi)容。借助這個(gè) ?TemplateRef
?,組件可以使用 ?ngTemplateOutlet
?指令或?ViewContainerRef.createEmbeddedView()
?方法來渲染所引用的內(nèi)容。
@Directive({
selector: '[appExampleZippyContent]'
})
export class ZippyContentDirective {
constructor(public templateRef: TemplateRef<unknown>) {}
}
在上一步中,你已添加了具有自定義屬性 ?appExampleZippyDirective
?的 ?<ng-template>
? 元素。這段代碼提供了當(dāng) Angular 遇到該自定義屬性時(shí)要使用的邏輯。在這里,該邏輯指示 Angular 實(shí)例化這個(gè)模板引用。
@ContentChild
? 獲取此投影內(nèi)容的模板。@ContentChild(ZippyContentDirective) content!: ZippyContentDirective;
在執(zhí)行此步驟之前,你的應(yīng)用具有一個(gè)組件,它會(huì)在滿足某些條件時(shí)實(shí)例化此模板。你還創(chuàng)建了一個(gè)指令,該指令能提供對(duì)該模板的引用。在最后一步中,?@ContentChild
? 裝飾器指示 Angular 實(shí)例化指定組件中的模板。
如果是多插槽內(nèi)容投影,則可以使用 ?
@ContentChildren
? 獲取投影元素的查詢列表(QueryList)。
如多插槽內(nèi)容投影中所述,你通常會(huì)使用屬性、元素、CSS 類或這三者的某種組合來標(biāo)識(shí)將內(nèi)容投影到何處。例如,在以下 HTML 模板中,p 標(biāo)簽會(huì)使用自定義屬性 ?question
?將內(nèi)容投影到 ?app-zippy-multislot
? 組件中。
<app-zippy-multislot>
<p question>
Is content projection cool?
</p>
<p>Let's learn about content projection!</p>
</app-zippy-multislot>
在某些情況下,你可能希望將內(nèi)容投影為其他元素。例如,你要投影的內(nèi)容可能是另一個(gè)元素的子元素??梢杂?nbsp;?ngProjectAs
?屬性來完成此操作。
例如,考慮以下 HTML 代碼段:
<ng-container ngProjectAs="[question]">
<p>Is content projection cool?</p>
</ng-container>
本示例使用 ?<ng-container>
? 屬性來模擬將組件投影到更復(fù)雜的結(jié)構(gòu)中。
注意!
?<ng-container>
? 元素是一個(gè)邏輯結(jié)構(gòu),可用于對(duì)其他 DOM 元素進(jìn)行分組;但是,?<ng-container>
? 本身未在 DOM 樹中渲染。
在這個(gè)例子中,我們要投影的內(nèi)容位于另一個(gè)元素內(nèi)。為了按預(yù)期方式投影此內(nèi)容,此模板使用了 ?ngProjectAs
?屬性。有了 ?ngProjectAs
?,就可以用 ?[question]
? 選擇器將整個(gè) ?<ng-container>
? 元素投影到組件中。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: