Angular学习笔记89: 父子组件内容投影进阶

本文详细介绍了在Angular开发中如何使用内容投影(ng-content)将DOM元素传递给子组件,并展示了如何设置默认投影、多个投影以及通过@Input传入变量进行投影。同时,还探讨了如何在子组件中使用父组件提供的上下文内容,包括单插槽、多插槽以及带有上下文的投影。这对于理解Angular组件间的通信和定制化渲染非常重要。
摘要由CSDN通过智能技术生成

实际开发过程的场景

在实际开发过程中,会遇到讲一个DOM 作为一个Input传给子组件,然后在子组件投影渲染出来。

  1. 子组件设置默认投影
  2. 子组件设置多个投影
  3. 在父组件中使用投影中的上下文内容

具体实现

创建两个组件,一个父组件ContentShadowUseComponent,一个子组件ContentShadowComponent

子组件设置默认投影
  1. 在子组件ContentShadowComponent中设置单插槽投影,可以使用<ng-content></ng-content>
<h3>内容投影</h3>

<h4>默认内容投影</h4>
<ng-content></ng-content>

  1. 在父组件ContentShadowUseComponent使用:
<app-content-shadow>
  默认的投影内容 - used
</app-content-shadow>

这种使用方式,即在父组件中使用的子组件中,所有的DOM都属于投影内容,在子组件设置<ng-content></ng-content>全部渲染出来,这里的<ng-content></ng-content>只是占位符,元素本身不会创建DOM

子组件从父组件传入的变量进行投影
  1. 在子组件ContentShadowComponent的类文件中定义一个变量
import {Component, Input, OnInit, TemplateRef} from '@angular/core';

@Component({
  selector: 'app-content-shadow',
  templateUrl: './content-shadow.component.html',
  styleUrls: ['./content-shadow.component.less']
})
export class ContentShadowComponent implements OnInit {
  @Input() inputContainer: TemplateRef<void>;

  constructor() {
  }

  ngOnInit(): void {
  }

}

  1. 在子组件ContentShadowComponent的模版文件中使用此变量
<h4>@Input投影</h4>
<ng-container *ngTemplateOutlet="inputContainer"></ng-container>
  1. 在父组件ContentShadowUseComponent中使用子组件
<app-content-shadow [inputContainer]="inputContainer">
  默认的投影内容 - used
</app-content-shadow>

<ng-template #inputContainer>
  inputContainer的投影内容 ~~~ -- used
</ng-template>

这个时候,DOM inputContainer的投影内容 ~~~ -- used会在子组件的<ng-container *ngTemplateOutlet="inputContainer"></ng-container>处投影,多使用于按条件投影。

多个插槽的投影
  1. 在子组件ContentShadowComponent的模版文件中,给ng-content标签添加一个select属性,select属性支持签名、属性、CSS 类和 :not 伪类的任意组合。
<h4>多个插槽投影</h4>
<ng-content select="[concept]"></ng-content>

这里是给ng-content添加了一个属性为concept,即在使用过程中,带有属性concept会投影在这个ng-content

  1. 在父组件ContentShadowUseComponent使用
<app-content-shadow [inputContainer]="inputContainer">
  默认的投影内容 - used
  <p concept>
    多个投影的内容 -- used
  </p>
</app-content-shadow>
在父组件中使用投影中的上下文内容
  • 在父组件中使用投影中的默认的上下文内容
  1. 修改子组件的模版文件
<h3>内容投影</h3>

<h4>默认内容投影</h4>
<ng-content></ng-content>
<nz-divider></nz-divider>
<h4>多个插槽投影</h4>
<ng-content select="[concept]"></ng-content>
<nz-divider></nz-divider>
<h4>@Input投影</h4>

<ng-container *ngTemplateOutlet="inputContainer"></ng-container>
<nz-divider></nz-divider>

<h4>@Input投影添加上下文</h4>

<ng-container *ngTemplateOutlet="inputContainerContext;context: containerContext"></ng-container>
  1. 在子组件中定义变量containerContext
import {Component, Input, OnInit, TemplateRef} from '@angular/core';

@Component({
  selector: 'app-content-shadow',
  templateUrl: './content-shadow.component.html',
  styleUrls: ['./content-shadow.component.less']
})
export class ContentShadowComponent implements OnInit {
  @Input() inputContainer: TemplateRef<void>;
  @Input() inputContainerContext: TemplateRef<void>;

  public containerContext = {
    $implicit: 'ContentShadow: 默认的投影上下文 --- 默认的投影上下文',
  };

  constructor() {
  }

  ngOnInit(): void {
  }

}

  1. 在父组件中使用
<app-content-shadow [inputContainer]="inputContainer"
                    [inputContainerContext]="inputContainerContext">
  默认的投影内容 - used
  <p concept>
    多个投影的内容 -- used
  </p>
</app-content-shadow>

<ng-template #inputContainer>
  inputContainer的投影内容 ~~~ -- used
</ng-template>

<ng-template #inputContainerContext let-content>
  带有上下文的投影,上下文为: {{content}}  -- used
</ng-template>

这里在父组件中就可以使用来自子组件的上下文内容了

  • 在父组件中使用投影中的其他的上下文内容
  1. 修改子组件的模版文件
<h3>内容投影</h3>

<h4>默认内容投影</h4>
<ng-content></ng-content>
<nz-divider></nz-divider>
<h4>多个插槽投影</h4>
<ng-content select="[concept]"></ng-content>
<nz-divider></nz-divider>
<h4>@Input投影</h4>

<ng-container *ngTemplateOutlet="inputContainer"></ng-container>
<nz-divider></nz-divider>

<h4>@Input投影添加上下文</h4>

<ng-container *ngTemplateOutlet="inputContainerContext;context: containerContext"></ng-container>
<nz-divider></nz-divider>

<h4>@Input投影添加其他上下文</h4>
<ng-container *ngTemplateOutlet="inputContainerContextOther;context: containerContext"></ng-container>
<nz-divider></nz-divider>
  1. 修改子组件中定义变量containerContext
import {Component, Input, OnInit, TemplateRef} from '@angular/core';

@Component({
  selector: 'app-content-shadow',
  templateUrl: './content-shadow.component.html',
  styleUrls: ['./content-shadow.component.less']
})
export class ContentShadowComponent implements OnInit {
  @Input() inputContainer: TemplateRef<void>;
  @Input() inputContainerContext: TemplateRef<void>;
  @Input() inputContainerContextOther: TemplateRef<void>;

  public containerContext = {
    $implicit: 'ContentShadow: 默认的投影上下文 --- 默认的投影上下文',
    otherContext: 'ContentShadow: 其他的投影上下文  -- --  --  其他的投影上下文'
  };

  constructor() {
  }

  ngOnInit(): void {
  }

}

  1. 在父组件中使用
<app-content-shadow [inputContainer]="inputContainer"
                    [inputContainerContext]="inputContainerContext"
                    [inputContainerContextOther]="inputContainerContextOther">
  默认的投影内容 - used
  <p concept>
    多个投影的内容 -- used
  </p>
</app-content-shadow>

<ng-template #inputContainer>
  inputContainer的投影内容 ~~~ -- used
</ng-template>

<ng-template #inputContainerContext let-content>
  带有上下文的投影,上下文为: {{content}}  -- used
</ng-template>

<ng-template #inputContainerContextOther let-content="otherContext">
  带有上下文的投影,上下文为: {{content}}  -- used
</ng-template>

这里使用let-content="otherContext"来确定使用来自子组件上下文中的otherContext变量

示例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o4EaD9am-1640934087453)(evernotecid://DD876EEF-E183-4B43-8B00-6200041EC9E3/appyinxiangcom/22553815/ENResource/p1120)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值