问题形容
我创立了一个 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 框架解析成须要被投影的节点。