0
点赞
收藏
分享

微信扫一扫

Angular 内容投影 content projection 的一个问题的单步调试


问题描述

我使用如下代码测试一个最简单的 Angular 内容投影场景:

import { Component } from '@angular/core';

@Component({
selector: 'app-zippy-basic',
template: `
<h2>Single-slot content projection</h2>
<ng-container></ng-container>
`
})
export class ZippyBasicComponent {}

Angular 内容投影 content projection 的一个问题的单步调试_占位符

我期望 ​​app-zippy-basic​​​ 的使用者,将传入的 ​​content​​​,投射到元素 ​​ng-container​​ 内部。

消费代码如下图所示:

<app-zippy-basic>
<p>Is content projection cool?</p>
<div>ok</div>
</app-zippy-basic>

然而运行时,我在渲染出的页面里,根本看不到 ​​Is content projection cool?​​ 的显示。

Angular 内容投影 content projection 的一个问题的单步调试_占位符_02

问题分析

打开 Chrome 开发者工具,发现 ​​app-zippy-basic​​ 内部只有一个 comment 节点:ng-container

Angular 内容投影 content projection 的一个问题的单步调试_开发者工具_03

我们在提供内容投影插槽的 Component 的 ng-container 之间随便键入一些字符串,例如 DIV:

Angular 内容投影 content projection 的一个问题的单步调试_开发者工具_04

渲染后发现,ng-container 没能按照我们期望的工作。

Angular 内容投影 content projection 的一个问题的单步调试_html_05

通过查阅 Angular 官网,发现这里把 ng-container 和 ng-content 弄混淆了。此处应该使用 ng-content.

解决方案

​ng-content​​ 之间不允许再插入其他元素。仅仅充当一个占位符的角色。

Angular 内容投影 content projection 的一个问题的单步调试_开发者工具_06

使用 ​​ng-content​​ 之后问题消失。这里我们可以通过单步调试的方式,搞清楚被投影的内容是如何插入到 ng-content 占位符里的。

Angular 内容投影 content projection 的一个问题的单步调试_html_07

选择 ​​app-zippy-basic​​​,给其设置一个 dom 断点,类型为 ​​subtree modification​​:

Angular 内容投影 content projection 的一个问题的单步调试_开发者工具_08

首先执行 template 函数,将 Component 本身的 h2 元素,进行 HTML 源代码的渲染:

Angular 内容投影 content projection 的一个问题的单步调试_开发者工具_09

Angular 内容投影 content projection 的一个问题的单步调试_开发者工具_10

接下来是 Angular 处理整个内容投影逻辑的关键:

Angular 内容投影 content projection 的一个问题的单步调试_开发者工具_11

遇到 ​​ng-content​​​,则调用函数 ​​ɵɵprojection​​:

Angular 内容投影 content projection 的一个问题的单步调试_开发者工具_12

转而调用 ​​applyProjection​​:

Angular 内容投影 content projection 的一个问题的单步调试_html_13

parent node 即是指定义了 ​​ng-content​​ 的 Component 对应的 dom 元素:

Angular 内容投影 content projection 的一个问题的单步调试_开发者工具_14

rNode 即是被插入到 ​​app-zippy-basic​​​ 中的节点,即 ​​app-zippy-basic​​ 的消费者。

Angular 内容投影 content projection 的一个问题的单步调试_占位符_15

消费语法:

<app-zippy-basic>
此处插入你想投影到 app-zippy-basic 内部的 HTML 源代码
</app-zippy-basic>



举报

相关推荐

0 条评论