iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
Modern Web

從巨人的 Tip 看 Angular系列 第 21

[Day 21] 關於 Content Projection

  • 分享至 

  • twitterImage
  •  

今天要分享的是關於 Angular 的 content projection。

Angular 提供了一個 ng-content 的 tag 來將其他的 HTML content 投影到 component template 內部,也就是標題所提到的 Content Projection。

來上個圖:

https://ithelp.ithome.com.tw/upload/images/20201006/20129148IbC831UwvZ.png

↑ Image 1:沒有使用 ng-content

https://ithelp.ithome.com.tw/upload/images/20201006/20129148s6uAZLrC0G.png

↑ Image 2:使用 ng-content

Image 1 的右邊是沒有使用 ng-content 的 ProjectComponent HTML template,當其他的 component 使用 app-projection 這個 tag 的時候,不管在 app-project tag 的中間放多少個元素,最終渲染出來的結果依然是 HTML template 內已經寫好的樣子。所以當你有許多個 component 都會需要用到 ProjectComponent 但每次都會有一點不同的時候,你可能就會需要針對個別情況做不同的處理。

但如果採用像是 Image 2,使用 ng-content 的方式來設計 ProjectComponent 的話,你就可以將某些固定的元素寫進 ProjectComponent 的 HTML template 內,需要個別客製化的內容則是在該 component 做其他調整。

進階一點的用法:multi ng-content

接下來要來介紹要如何使用多個 ng-content 來讓外部投影到內部的內容可以有更多的變化。

https://ithelp.ithome.com.tw/upload/images/20201006/20129148y2J0PrBZho.png
↑ Image 3:multi ng-content 的用法

當有多個 ng-content 存在於同一個 HTML template 的時候,我們可以透過 select 這個 attribute 來指定這個 ng-content 要投影外部的哪一個元素:

 <ng-content select=".header"></ng-content>

↑ Block 1

以 Block 1 的程式碼範例來說,這個 ng-content 會選擇 CSS class 名稱符合 header 的元素來投影。

這邊給各位一個重點:select 接受任何符合 CSS selector 規範的字串。

所以我們可以像 Block 1 一樣用 . 來代表 class,也可以像下面一樣用 tag 或是 attribute:

<!-- 以 attribute 做選擇依據-->
<ng-content select="[footer]"></ng-content>

<!-- 以 tag 做選擇依據 -->
<ng-content select="p"></ng-content>

↑ Block 2

到這邊或許會有人好奇,當有多個元素符合 select 的話會怎麼樣?

答案是:都選,且按順序顯示。

<app-mproject>
  <div footer>
    <p>FOOTER</p>
  </div>
  <div class="header">
    <p>HEADER</p>
  </div>
  <p>Not a footer is a p element</p>
  <span>Third</span>
  <p class="header">Second</p>
</app-mproject>

↑ Block 3:AppComponent HTML template

<div style="border: 2px solid orange; margin-top: 1px; padding: 1rem;">
  <ng-content select=".header"></ng-content>
  <div style="margin-left: 1rem">
    <p>mproject works!</p>
  </div>
  <ng-content select="[footer]"></ng-content>
</div>
<ng-content select="p"></ng-content>

↑ Block 4:MprojectComponent HTML tempate

以 Block 3 與 Block 4 為例子來看的話,最終 render 的結果會是:

https://ithelp.ithome.com.tw/upload/images/20201006/201291483ydNULJk9a.png

↑ Image 4

首先 <span>Third</span> 的部分不見了,因為在 MprojectionComponent 內並沒有任何的 ng-content 選取到這個元素,但若 template 內有一個 ng-content 不包含 selector 的話,這些被遺忘的元素就會被放到裡面。

接著看一下 select=".header" 的部分,符合的元素有兩個,一個是被包在 div 內的 p,另一個則是 <p>Second</p>,這些符合 select 條件的元素都被按照出現的順序,全部被投影到最上面。再來是符合 select="[footer]" 的元素,最後則是符合 select="p" 的元素。

至於選擇的優先順序,相信不用我多說,各位也一定可以找出規律的!


以上就是今天要分享給各位的內容,明天會再接著探討 Angular 是怎麼解析以及處理 ng-content tag!

星期二,第 21 天 ?

以下按照入團順序列出我們團隊夥伴的系列文章!

請自由參閱 ?


上一篇
[Day 20] ElementRef、TemplateRef、ViewContainerRef ???
下一篇
[Day 22] 深度探討 ng-content 背後的機制 (1)
系列文
從巨人的 Tip 看 Angular30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言