angular - slot概念

1,052 阅读2分钟

来自官网学习个人总结

单插槽

父组件欲在子组件中自定义插槽 可使用<ng-content>:
🌰 有组件BasicComponent

//父
<app-basic>
  <p> hello 🙂 hello </p>
</app-basic>
//BasicComponent
import { Component } from '@angular/core';

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

多插槽

 为 <ng-content>添加 select 属性就可以选择渲染特定插槽.
Angular 支持所有标签名,属性,css-class 与伪类:not的 selectors 

🌰

//app.component.html
<app-zippy-multislot>
  <p></p>
  <p question>吃饭了吗</p>
</app-zippy-multislot>
//zippy-multislot.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-zippy-multislot',
  template: `
    <h2>多槽处理案例</h2>

    默认插槽:
    <ng-content></ng-content>

    '问题'插槽:
    <ng-content select="[question]"></ng-content>
  `
})
export class ZippyMultislotComponent {}

条件渲染插槽

使用<ng-template>组件。可以根据你设置的条件明确渲染组件。
<ng-content>相比,它能够在条件符合的时候再去初始化要渲染的组件。
👣steps:

  1. 创建组件
  2. <ng-container>组件中接收ngTemplateOutlet 。

你可以在任意组件上使用 ngTemplateOutlet 指令。因为这个组件并不需要真的渲染出DOM,就使用在 <ng-template>

//example-zippy.template.html
<ng-container [ngTemplateOutlet]="content.templateRef"></ng-container>
  1. 再添加上条件逻辑。
//example-zippy.template.html
<div *ngIf="expanded" [id]="contentId">
    <ng-container [ngTemplateOutlet]="content.templateRef"></ng-container>
</div>
  1. 在你需要使用刚在所封装好的组件时,添加<ng-template>指定渲染
    <ng-template>的添加等于添加一个块元素。
    下例,我们自定义了appExampleZippyContent指令去标记 <ng-template>
    一个组件可以通过TemplateRef获得标签内content。记得使用@ContentChild 或 @ContentChildren装饰进行参考渲染。
    TemplateRef的使用让组件可以通过ngTemplateOutlet指令或ViewContainerRef 的 createEmbeddedView()方法去渲染内容。
//app.template.html
<ng-template appExampleZippyContent>
  被条件渲染的语句.
</ng-template>
  1. 为你的组件创建一个自定义指令 . 在这个指令中注入一个TemplateRef 实例.
    在之前的操作中,你已经在 <ng-template>中添加了自定义指令appExampleZippyContent
    下面的代码为 Angular提供遇见appExampleZippyContent后所要运行的逻辑。 本例中为指引Angular实例化模板引用。
//app.component.ts
@Directive({
  selector: '[appExampleZippyContent]'
})
export class ZippyContentDirective {
  constructor(public templateRef: TemplateRef<unknown>) {}
}
  1. 在要投影内容的组件中,使用@ContentChild获取投影内容的模板。

下例中 @ContentChil d装饰器将使 Angular 在指定组件中实例化模板。

//app.component.ts
@ContentChild(ZippyContentDirective) content!: ZippyContentDirective;