angular内容投影详解

2022-07-19,,,

内容投影

利用ng-content来实现

<!-- 组件 - app-content-single -->
<div>
  <h2>标题</h2>
  <!-- 投影内容显示位置 -->
  <ng-content></ng-content>
</div>
<!-- 使用 -->
<app-content-single>
  <div>this is content</div>
</app-content-single>

多内容投影

利用ng-content来实现

<!-- 组件 - app-content-more -->
<div>
  <h3>herder title</h3>
  <ng-content select=".header"></ng-content>
  <h3>body title</h3>
  <ng-content select="[body]"></ng-content>
  <h3>default title</h3>
  <ng-content></ng-content>
  <h3>footer title</h3>
  <ng-content select="footer"></ng-content>
</div>
<!-- 使用 -->
<app-content-more>
  <div>this is default01</div>
  <div class="header">this is header</div>
  <div>this is default02</div>
  <div body>this is body</div>
  <div>this is default03</div>
  <footer>this is footer</footer>
  <div>this is default04</div>
</app-content-more>

有条件的内容投影-ng-template, ng-container, directive 等来配合实现

单个条件的内容投影

eg: 假设现在有一个人员列表,当某个人的money大于200的时候,额外添加组件中模板定义的内容

定义一个 appchildref 指令来配合 ng-template 获取模板

import { directive, templateref } from '@angular/core';
@directive({
  selector: '[appchildref]'
})
export class childrefdirective {
  constructor(public templateref: templateref<any>) { }
}

app-persons - html

<div class="list-item" *ngfor="let person of persons;">
  <div>name: {{ person.name }}</div>
  <div>money: {{ person.money }}</div>
  <div *ngif="person.money > 200">
    <ng-container *ngif="childref" [ngtemplateoutlet]="childref.templateref"></ng-container>
  </div>
</div>

app-persons - ts

import { component, contentchild, oninit } from '@angular/core';
import { childrefdirective } from '../../../../directives/child-ref.directive';
@component({
  selector: 'app-persons',
  templateurl: './persons.component.html',
  styleurls: ['./persons.component.scss']
})
export class personscomponent implements oninit {
  persons: { name: string; money: number; }[] = [
    { name: '杰克', money: 120 },
    { name: '李莉', money: 210 },
    { name: '张三', money: 170 },
  ];
  @contentchild(childrefdirective, { static: true }) childref!: childrefdirective;
  constructor() { }
  ngoninit(): void { }
}

使用

<app-persons>
  <ng-template appchildref>
    <div style="font-size: 14px; color: red;">this is child ref content</div>
  </ng-template>
</app-persons>

效果图

多个条件内容投影

eg: 现在希望通过 persons 数据中的字段进行绑定内嵌的模板来显示

appchildref 调整

import { directive, input, templateref } from '@angular/core';
@directive({
  selector: '[appchildref]'
})
export class childrefdirective {
  // 接受定义模板名称-通过这个名称和 persons 中的render字段对应进行显示对应的模板内容
  @input() appchildref!: string;
  constructor(public templateref: templateref<any>) { }
}

app-persons - html

<div class="list-item" *ngfor="let person of persons;let i=index;">
  <div>name: {{ person.name }}</div>
  <div>money: {{ person.money }}</div>
  <!-- <div *ngif="person.money > 200">
    <ng-container *ngif="childref" [ngtemplateoutlet]="childref.templateref"></ng-container>
  </div> -->
  <div *ngif="person.render && temprefs[person.render]">
    <!-- 配合 ngtemplateoutlet 指令给template传递当前person的数据 -->
    <ng-container *ngtemplateoutlet="temprefs[person.render].templateref; context: { $implicit: person, i: i }"></ng-container>
  </div>
</div>

app-persons - ts

import { component, contentchild, contentchildren, oninit, querylist } from '@angular/core';
import { childrefdirective } from '../../../../directives/child-ref.directive';
@component({
  selector: 'app-form-unit',
  templateurl: './form-unit.component.html',
  styleurls: ['./form-unit.component.scss']
})
export class formunitcomponent implements oninit {
  persons: { name: string; money: number; render?: string; }[] = [
    { name: '杰克', money: 120, render: 'temp1' },
    { name: '李莉', money: 210, render: 'temp2' },
    { name: '张三', money: 170, render: 'temp3' },
  ];
  // @contentchild(childrefdirective, { static: true }) childref!: childrefdirective;
  @contentchildren(childrefdirective) childrenref!: querylist<childrefdirective>;
  get temprefs() {
    const aobj: any = {};
    this.childrenref.foreach(template => {
      const key: string = template.appchildref;
      aobj[key] = template;
    })
    return aobj;
  }
  constructor() { }
  ngoninit(): void { }
}

使用

<app-persons>
  <ng-template appchildref="temp1" let-person let-index="i">
    <div style="font-size: 14px; color: red;">{{index}}-{{person.name}}: this is temp1</div>
  </ng-template>
  <ng-template appchildref="temp2" let-person let-index="i">
    <div style="font-size: 14px; color: green;">{{index}}-{{person.name}}: this is temp2</div>
  </ng-template>
  <ng-template appchildref="temp3" let-person let-index="i">
    <div style="font-size: 14px; color: orange;">{{index}}-{{person.name}}: this is temp3</div>
  </ng-template>
</app-persons>

效果图

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!

《angular内容投影详解.doc》

下载本文的Word格式文档,以方便收藏与打印。