通過單步除錯的方式學習 Angular 中帶有選擇器的內容投影使用方式
問題描述
我建立了一個 selector 為 app-content-section
的 Component,用於容納內容投影(content projection
):
這個 Component 的模板區域,分別定義了三個 div 區域,裡面包含了對應的內容投影占位符 ng-content
:
第一個綠色區域接收所有 div 標籤,第二個藍色區域接收所有包含了 css class content-class
的標籤,第三個區域接收所有 name 屬性值為 test 的標籤。
我們來看看消費這個 Component 的程式碼:
<app-content-section> <div name="test">div[name="test"]</div> <div>純粹的 div 標籤</div> <p #six class="content-class">p 標籤,包含 [class="content-class] 和 six id</p> <p name="test">p 標籤 [name="test"]</p> </app-content-section>
app-content-section
中包含兩個 div 元素,故最後的綠色區域裡,包含了兩個 div 值:
藍色區域內只顯示了一個 p 標籤,因為這是消費者傳入的元素裡,唯一一個帶有 content-class
類的元素。
接下來的問題是,消費者傳入的元素裡,第一個 div 元素和最後一個 p 元素的 name
屬性值都為 test
,為什麼只有最後一個 p 標籤,被投影到 app-content-section
裡呢?
問題分析
第一個 div 標籤同時滿足第一條和第三條內容投影規則,因此其被投影到第一個 ng-content
之後,就不會再重複被投影了。
我們可以做一個測試,把提供內容投影場所的 Component 內的第一個和第三個 ng-content
這次的測試結果,紅色區域出現的兩個元素,其 name 屬性值都為 test. 而雖然綠色區域容納的是被投射的 div 元素,但是因為 name = test 的 div 元素,已經被優先投射到紅色區域,所以它不會再被重複投射了。
總結
通過單步除錯 Angular content projection 的相關程式碼,也能確認上述邏輯。
當 Component 的模板檔案被解析,遇到 ng-content
時:
觸發 ɵɵprojection
函式。
applyProjectionRecursive
函式裡的 nodeToProject
,就是需要被投影的 DOM 節點:
可以看到這裡只有包含了 name = test 屬性值的 div 被 Angular 框架解析成需要被投影的節點。