通过单步调试的方式学习 Angular 中带有选择器的内容投影使用方式

举报
汪子熙 发表于 2022/11/06 14:43:29 2022/11/06
【摘要】 问题描述我创建了一个 selector 为 app-content-section 的 Component,用于容纳内容投影(content projection):这个 Component 的模板区域,分别定义了三个 div 区域,里面包含了对应的内容投影占位符 ng-content:第一个绿色区域接收所有 div 标签,第二个蓝色区域接收所有包含了 css class content-...

问题描述

我创建了一个 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 框架解析成需要被投影的节点。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。