Content顾名思义是内容,它与放置在
里面的投影内容息息相关。
1. 回顾一下ng-content
greet.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'exe-greet',
template: `
// 投影处
`,
styles: [` .border { border: 2px solid #eee; } `]
})
export class GreetComponent { }
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
Welcome to Angular World
Hello Minghao
// 在exe-greet标签中放置的内容将会投影到ng-content处
`,
})
export class AppComponent { }
此时网页上输出的内容,假设我们将 my-app 的template内容显示出来
Welcome to Angular World
Hello Minghao
// exe-greet的内容如左边所示
2. ng-content支持select属性
有人可能会说上面那样太简单了,实际需求中可能会稍微复杂一些,要插入的内容需要自定义,甚至是放入某些节点里面包裹起来,而且可能有不同的组件需要用到greet这个组件,行,那我们来改进一下。
import { Component } from '@angular/core';
@Component({
selector: 'exe-greet',
template: `
Greet Component
// 标签选择器
// 类选择器
// 标签选择器
`,
styles: [` .border { border: 2px solid #eee; } `]
})
export class GreetComponent{ }
GreetComponent 组件已经调整好了,现在剩下的问题就是如何从父级组件动态的抽取各个部分的内容。幸运的是,ng-content
指令支持 select
属性,它允许我们设定抽取的内容,更强大的是它支持我们常用的选择器类型,如标签选择器、类选择器、ID选择器、属性选择器
等。
下面来改善一下父模板app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
Welcome to Angular World
Card Header
Card Body
`,
})
export class AppComponent { }
此时网页上输出的内容,假设我们将 my-app 的template内容显示出来
Welcome to Angular World
Greet Component
Card Header // 标签选择器
Card Body // 类选择器
// 标签选择器
3. 切入正题,谈谈@ContentChild
child.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'exe-child',
template: `
Child Component
`
})
export class ChildComponent {
name: string = 'child-component';
}
parent.component.ts
import { Component, ContentChild, AfterContentInit } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'exe-parent',
template: `
Parent Component
`
})
export class ParentComponent implements AfterContentInit {
@ContentChild(ChildComponent)
childCmp: ChildComponent;
ngAfterContentInit() {
console.dir(this.childCmp);
}
}
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
Welcome to Angular World
`,
})
export class AppComponent { }
以上代码运行后,控制台的输出结果:
ContentChildren
ContentChildren 属性装饰器用来从通过 Content Projection 方式设置的视图中获取匹配的多个元素,返回的结果是一个 QueryList 集合。
parent.component.ts
import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'exe-parent',
template: `
Parent Component
`
})
export class ParentComponent implements AfterContentInit {
@ContentChildren(ChildComponent)
childCmps: QueryList;
ngAfterContentInit() {
console.dir(this.childCmps);
}
}
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
Welcome to Angular World
`,
})
export class AppComponent { }
以上代码运行后,控制台的输出结果:
Something else
-
ContentChildren 与 ViewChildren 的定义
在 host 元素
和 标签中被称为 Content Children 在组件的模板中定义的内容,它是组件的一部分,被称为 View Children
-
ContentChild 与 ViewChild 的异同点
-
相同点
1.都是属性装饰器
2.都有对应的复数形式装饰器:ContentChildren、ViewChildren
3.都支持 Type
-
不同点
1.ContentChild 用来从通过 Content Projection 方式 (ng-content) 设置的视图中获取匹配的元素
2.ViewChild 用来从模板视图中获取匹配的元素
3.在父组件的 ngAfterContentInit 生命周期钩子中才能成功获取通过 ContentChild 查询的元素
4.在父组件的 ngAfterViewInit 生命周期钩子中才能成功获取通过 ViewChild 查询的元素
(reference by semlinker)