美文网首页
Angular 内容投影 content projection

Angular 内容投影 content projection

作者: _扫地僧_ | 来源:发表于2022-03-16 10:40 被阅读0次

    问题描述

    我使用如下代码测试一个最简单的 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 {}
    

    我期望 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? 的显示。

    问题分析

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

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

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

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

    解决方案

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

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

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

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

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

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

    转而调用 applyProjection

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

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

    消费语法:

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

    相关文章

      网友评论

          本文标题:Angular 内容投影 content projection

          本文链接:https://www.haomeiwen.com/subject/exkerrtx.html