1. 程式人生 > 其它 >通過單步除錯的方式學習 Angular 中帶有選擇器的內容投影使用方式

通過單步除錯的方式學習 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 框架解析成需要被投影的節點。