13Angular组件投影

2020-12-25  本文已影响0人  learninginto

用法类似于ViewChild,获取投影中的组件、指令和dom元素,类似于vue中的具名插槽和匿名插槽

import { Component, Input, TemplateRef } from '@angular/core';
@Component({
  selector: 'app-shadow',
  template: `
            <div class="shadow">
              <div class="head">
                <ng-content select=".head"></ng-content>
              </div>
              <div class="body">
                <ng-content select="[attr]"></ng-content>
                <ng-content select="article"></ng-content>
                <ng-content></ng-content>
              </div>
              <div class="foot">
                <ng-content select=".foot"></ng-content>
              </div>
            </div>`
})
export class ShadowComponent  {}
import { Component, Input } from '@angular/core';
@Component({
  selector: 'app-root',
  template: `
            <app-shadow [visible]="true">
              <div class="head">这是head的投影</div>
              <div attr>这是attr的投影内容</div>
              <article>这是article的投影内容</article>
              <b style="color: #007bff">这是默认的投影内容</b>
              <div class="foot">这是foot的投影</div>
            </app-shadow>
          `
})
export class AppComponent  {}
获取投影中的组件
import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core';

@Component({
  selector: 'app-content-child-panel',
  templateUrl: './content-child-panel.component.html'
})
export class ContentChildPanelComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {}

  alert() {
    alert('aa');
  }
}

@Component({
  selector: 'app-content-child',
  template: `
      <div class="content-child-box">
        <h2>这是content child组件</h2>
        <div class="head" style="border: 1px solid; margin: 10px 0;">
          <ng-content select=".head"></ng-content>
        </div>
        <ng-content></ng-content>
      </div>
 `,
  styles: []
})
export class ContentChildComponent implements AfterViewInit {
  // 无法获取dom元素
  // @ContentChild('.head', { static: true }) private headEl: ElementRef;
  // @ContentChild('list', { static: true }) private listEl: ElementRef;
  @ContentChild(ContentChildPanelComponent, { static: true }) private panel: ContentChildPanelComponent;
  constructor() { }

  ngAfterViewInit(): void {
    this.panel.alert();
  }

}
<app-content-child>
  <div class="head">
    这是头部
  </div>
  <app-content-child-panel></app-content-child-panel>
  <ul #list>
    <li>aaa</li>
    <li>bbb</li>
  </ul>
</app-content-child>

用法类似ViewChildren, 批量获取投影中到组件或指令

<app-content-child>
  <div class="head">
    这是头部
  <app-content-child-panel></app-content-child-panel>
  </div>
  <app-content-child-panel></app-content-child-panel>
  <app-content-child-panel></app-content-child-panel>
  <ul #list>
    <li>aaa</li>
    <li>bbb</li>
  </ul>
</app-content-child>
export class ContentChildComponent implements AfterViewInit {
  @ContentChildren(ContentChildPanelComponent) private panels: QueryList<ContentChildPanelComponent>;
  constructor() { }

  ngAfterViewInit(): void {
    console.log(this.panels); // 只有两个结果
  }

}

这里只能拿到两个panels,默认只寻找直属的panel 而.head里的panel组件嵌套了一层div,并非直属

想要拿到所有层级的panel组件,需要开启descendants属性

@ContentChildren(ContentChildPanelComponent, { descendants: true }) private panels: QueryList;
上一篇下一篇

猜你喜欢

热点阅读