Angular10教程–2.8 ContentChild与ContentChildren 装饰器

Angular10教程--2.8 ContentChild与ContentChildren 装饰器
跟我们上一节介绍的ViewChildViewChildren用法几乎一致。他们都是,但是区别在于,前者是获取投影(ng-content)中的、元素等。

@ContentChild()

ContentChild的元数据跟ViewChild一样,也是有下面三个:

  • selector - 用于查询的指令类型或名字。
  • read - 从查询到的元素中读取另一个令牌。
  • static - 如果为true,则在更改检测之前解析查询结果;如果为false,则在更改检测之后解析查询结果。默认为false

获取普通DOM

默认你已经了解<ng-content>的用法:

<!-- content-child.component.html -->
<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>

父组件传入内容:

<!-- app.component.html -->
<app-content-child>
   <p class="head">传入的头部</p>
   <p #other>其他内容</p>
</app-content-child>

获取元素:

// content-child.component.ts
...
export class ContentChildComponent implements OnInit, AfterViewInit {
   // 这样是获取不到元素的
   @ContentChild('.head', {static: true}) private headEl: ElementRef<HTMLSpanElement>;
   @ContentChild('other', {static: true}) private otherEl: ElementRef<HTMLDivElement>;
   constructor() { }
   ngOnInit(): void {}
   ngAfterViewInit(): void {
     console.log(this.headEl); // undefined
     console.log(this.otherEl.nativeElement); // <div _ngcontent-teu-c17="">其他内容</div>
   }
}
上面获取元素的方式有个特别注意的地方:ContentChild的selector参数不能是css的类选择器以及标签选择器!
tips:获取组件就不介绍了吧,如不熟悉,参阅上一节

@()

三个元数据介绍:

  • selector - 用于查询的指令类型或名字。
  • descendants - 如果为true,则包括所有后代,否则仅包括直接子代,默认false。
  • read - 用于从查询的元素中读取不同的标记。
用法类似ViewChildren, 批量获取投影中到组件或指令。
先创建一个子组件:
ng g c components/content-child/content-child-panel -s
修改content-child组件:
<!-- content-child.component.html -->
<div class="content-child-box">
   <h2>这是content child组件</h2>
   <ng-content></ng-content>
</div>
传入三个content-child-panel组件:
<!-- app.component.html -->
<app-content-child>
   <app-content-child-panel></app-content-child-panel>
   <app-content-child-panel></app-content-child-panel>
   <div class="foot">
     <app-content-child-panel></app-content-child-panel>
   </div>
</app-content-child>
获取组件:
// content-child.component.ts
...
export class ContentChildComponent implements OnInit, AfterViewInit {
   @ContentChildren(ContentChildPanelComponent) private panels: QueryList<ContentChildPanelComponent>;
   constructor() { }
   ngOnInit(): void {}
   ngAfterViewInit(): void {
     console.log(this.panels);
  }
}
浏览器日志:

Angular10教程--2.8 ContentChild与ContentChildren 装饰器

从上面的结果可以看出:页面上显示了三个子组件,但是我们获取到的组件只有前两个,因为元数据中descendants默认为false
@ContentChildren(ContentChildPanelComponent, {descendants: true}) private panels: QueryList<ContentChildPanelComponent>;

总结

  1. ContentChildContentChildren是获取投影中的组件、指令及元素DOM等;
  2. ContentChildren开启descendants才能获得所有子组件。