內容投影
ng-content
ng-content
是一個占位符,有些類似於router-outlet
。
以前舉の例子,父組件包含子組件都是直接指明子組件的selector
,比如子組件的selector
叫app-child
,那么嵌入父組件時直接指明即可:
<app-child></app-child>
這是很硬性的編碼,而ng-content
就是用來替代這種硬性編碼的。
比如有個父組件這樣定義:
@Component({
selector: 'app-parent',
template: `
<p>Parent Component</p>
<div style="background: cyan">
<ng-content></ng-content>
</div>
`
})
它表示被放進的內容的背景色統一設置為cyan
。
接下來就要將子組件放入父組件中,放置的方式很簡單,在根組件中將app-child
插入到app-parent
中即可:
<app-parent>
<app-child></app-child>
</app-parent>
多個投影
上例中只有一個投影,那么多個投影怎么辦呢?<ng-content>
支持一個 select
屬性,可以讓你在特定的地方投射具體的內容。該屬性支持 CSS 選擇器(my-element
,.my-class
,[my-attribute]
,...)來匹配你想要的內容。如果 ng-content
上沒有設置 select
屬性,它將接收全部內容,或接收不匹配任何其他 ng-content 元素的內容。
比如父組件上有兩個可投影的位置,一個背景為淺綠,一個為粉紅:
<div style="background: cyan">
<ng-content select="[name=child]"></ng-content>
</div>
<div style="background: pink">
<ng-content select=".red"></ng-content>
</div>
此時可以在根組件上定義如下:
<app-parent>
<app-child class="red"></app-child>
<app-child name="child"></app-child>
</app-parent>
這樣就可以對號入座了!
ContentChild
理解了ng-content
就可以使用@ContentChild
裝飾器來調用投影內容了,它和@ViewChild
非常類似,就不多做介紹了,其異同點列舉如下:
相同點
- 都是屬性裝飾器
- 都有對應的復數形式裝飾器:ContentChildren、ViewChildren
- 都支持 Type
|Function|string 類型的選擇器
不同點
- ContentChild 用來從通過 Content Projection 方式 (ng-content) 設置的視圖中獲取匹配的元素
- ViewChild 用來從模板視圖中獲取匹配的元素
- 在父組件的 ngAfterContentInit 生命周期鈎子中才能成功獲取通過 ContentChild 查詢的元素
- 在父組件的 ngAfterViewInit 生命周期鈎子中才能成功獲取通過 ViewChild 查詢的元素