Maison > Article > interface Web > Un article pour comprendre les trois types de projection de contenu dans Angular (single slot, multi-slot, conditionnelle)
Cet article vous guidera à travers la projection de contenu dans angular et présentera la projection de contenu à emplacement unique, la projection de contenu à emplacements multiples et la projection de contenu conditionnel. J'espère qu'il sera utile à tout le monde !
【Recommandation de didacticiel connexe : "tutoriel angulaire"】
La projection de contenu à emplacement unique signifie créer un composant dans lequel vous pouvez projeter un composant.
zippy-basic.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-zippy-basic', template: ` <h2>单插槽内容投影</h2> <ng-content></ng-content> ` }) export class ZippyBasicComponent {}
Avec l'élément ng-content
, les utilisateurs de ce composant peuvent désormais projeter leurs propres messages dans le composant. Par exemple : ng-content
元素,该组件的用户现在可以将自己的消息投影到该组件中。例如:
app.component.html
<!-- 将 app-zippy-basic 元素包裹的全部内容投影到 zippy-basic 组件中去 --> <app-zippy-basic> <p>单插槽内容投影:投影数据</p> </app-zippy-basic>
效果如下:
ng-content 元素是一个占位符,它不会创建真正的 DOM 元素。
ng-content
的那些自定义属性将被忽略。
- 组件模板含有多个
ng-content
标签。- 为了区分投影的内容可以投影到对应
ng-content
标签,需要使用ng-content
标签上的select
属性作为识别。select
属性支持标签名、属性、CSS 类和 :not 伪类的任意组合。- 不添加
select
属性的ng-content
标签将作为默认插槽。所有为匹配的投影内容都会投影在该ng-content的位置。
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 {}
app.component.html
<!-- 使用 question 属性的内容将投影到带有 `select=[question]` 属性的 ng-content 元素。 --> <app-zippy-multislot> <p question style="color: hotpink;"> 带question属性的p元素 </p> <p style="color: lightgreen">不带question属性的p元素-->匹配到不带select属性的ng-content</p> <p>不带question属性的p元素-->匹配到不带select属性的ng-content</p> </app-zippy-multislot>
效果如下:
在前面的示例中,只有第二个 ng-content 元素定义了select 属性。结果,第一个 ng-content 元素就会接收投影到组件中的任何其他内容。
推荐使用
ng-container
标签,因为该标签不需要渲染真实的 DOM 元素。
<ng-container *ngTemplateOutlet="templateRefExp; context: contextExp"></ng-container> <!-- 等同 --> <ng-container [ngTemplateOutlet]="templateRefExp" [ngTemplateOutletContext]="contextExp"></ng-container>
参数 | 类型 | 说明 |
---|---|---|
templateRefExp | TemplateRef | null | 一个字符串,用于定义模板引用以及模板的上下文对象 |
contextExp | Object | null | 是一个对象,该对象的键名将可以在局部模板中使用 let 声明中进行绑定。在上下文对象中使用 $implicit 为键名时,将把它作为默认值。 |
ng-template
标签的#ID
会匹配templateRefExp
,将ng-template
标签的内容嵌入到指定的ngTemplateOutlet
中。
例一:
<header>头部</header> <main> <h3>内容:</h3> <ng-container [ngTemplateOutlet]="greet"></ng-container> </main> <footer>底部</footer> <ng-template #greet> <div> <h4>hi!</h4> <h4>hello my dear friend!</h4> </div> </ng-template>
效果:
ContentChild
:与内容子节点有关,操作投影进来的内容;ViewChild
:与视图子节点有关,操作自身的视图内容;在上一部分,我们通过内容投影,让自定义的组件标签能够嵌入html标签或自定义组件标签,那么它如何操作投影进来的内容呢?
首先创建两个组件
/**** part-b.component.ts ****/ import { Component, OnInit,Output} from '@angular/core'; @Component({ selector: 'app-content-part-b', templateUrl: './part-b.component.html', styleUrls: ['./part-b.component.scss'] }) export class PartBComponent implements OnInit { constructor() { } ngOnInit() { } public func():void{ console.log("PartB"); } }
/**** part-a.component.ts ****/ import { Component, OnInit, ContentChild } from '@angular/core'; // 1、引入 part-b 组件 import { PartBComponent } from '../part-b/part-b.component'; @Component({ selector: 'app-content-part-a', templateUrl: './part-a.component.html', styleUrls: ['./part-a.component.scss'] }) export class PartAComponent implements OnInit { // 2、获取投影 @ContentChild(PartBComponent) PartB:PartBComponent constructor() { } ngOnInit() {} ngAfterContentInit(): void { // 3、调用 part-b 组件的 func() 方法 this.PartB.func(); } public func() { console.log('PartA') } }
将part-b
组件的内容投影到part-a
组件中
<!-- content.component.html --> <div> <div>Content</div> <div> <app-content-part-a> <!-- 投影在part-a组件中的内容 --> <h1>PartA--start</h1> <app-content-part-b></app-content-part-b> <span>PartA--end</span> </app-content-part-a> </div> </div>
在组件的生命周期里面,有一个钩子
ngAfterContentInit()
是与投影内容初始化有关,所以我们有关投影的内容操作尽量放在它初始化完成之后进行
上一部分的ContentChild
操作的时投影进来的内容,而ViewChild
操作的是自身的视图内容
给上一部分的content.component.html
修改如下:
<!-- content.component.html --> <div> <div>Content</div> <div> <!-- 在此处引用模板变量 #partA --> <app-content-part-a #partA> <h1>PartA--start</h1> <app-content-part-b></app-content-part-b> <span>PartA--end</span> </app-content-part-a> </div> </div>
/**** content.component.ts ****/ import { Component, OnInit, ViewChild } from '@angular/core'; @Component({ selector: 'app-content', templateUrl: './content.component.html', styleUrls: ['./content.component.scss'] }) export class ContentComponent implements OnInit { // 2、获取视图 partA @ViewChild('partA') partA: any; constructor() { } ngOnInit() {} ngAfterViewInit(): void { // 3、调用 part-a 组件的 func() 方法 this.partA.func(); } }
ngAfterContentInit()
对应的是ngAfterViewInit()
(视图节点初始化是在投影内容初始化之后)
ContentChild
和ViewChild
还存在复数的形式,即ContentChildren
和ViewChildren
import { Component, OnInit, ContentChild,ContentChildren ,QueryList } from '@angular/core'; import { PartBComponent } from '../part-b/part-b.component'; @Component({ selector: 'app-content-part-a', templateUrl: './part-a.component.html', styleUrls: ['./part-a.component.scss'] }) export class PartAComponent implements OnInit { @ContentChildren(PartBComponent) PartBs: QueryList<PartBComponent>; constructor() { } ngOnInit() {} }L'effet est le suivant :
L'élément ng-content est un espace réservé, il ne crée pas un véritable élément DOM. Ces attributs personnalisés de ng-content
seront ignorés.
ng-content
. ng-content
correspondante, vous devez utiliser select
sur le ng -content
tag >Attribut comme identification. select
prend en charge toute combinaison de noms de balises, d'attributs, de classes CSS et de pseudo-classes :not. ng-content
sans ajouter l'attribut select
sera utilisée comme emplacement par défaut. Tout le contenu projeté correspondant sera projeté à la position du contenu ng. ng-container
car cette balise ne nécessite pas de rendu d'éléments DOM réels. 🎜🎜rrreeeParamètre | Type | Description |
---|---|---|
templateRefExp | TemplateRef | null | Une chaîne utilisée pour définir la référence du modèle et l'objet contextuel du modèle | contextExp | Object | null | est un objet dont le nom de clé peut être lié dans une instruction let dans un modèle local. Lorsque vous utilisez $implicit comme nom de clé dans un objet contextuel, il sera utilisé comme valeur par défaut. |
#ID
de la balise ng-template
correspondra à templateRefExp
, et le le contenu de la balise ng-template
est intégré dans le ngTemplateOutlet
spécifié. 🎜🎜Exemple 1 : 🎜rrreee🎜Effet : 🎜🎜🎜🎜🎜ViewChild et ContentChild🎜🎜ContentChild
: lié au sous-nœud de contenu, 🎜opère le contenu projeté🎜;ViewChild
: lié au nœud vue enfant, 🎜exploite son propre contenu de vue🎜 ;part-b
? au composant part-a
🎜rrreee🎜🎜Dans le cycle de vie du composant, il y a un hook ngAfterContentInit()
qui est lié à l'initialisation du contenu projeté, nous nous préoccupons donc du contenu projeté Essayez d'effectuer l'opération une fois son initialisation terminée🎜🎜ContentChild
dans la partie précédente est le contenu projeté, while ViewChild
Ce qui fonctionne, c'est son propre contenu de vuecontent.component.html
de la partie précédente comme suit : 🎜rrreeerrreee🎜🎜ngAfterContentInit() correspond à <code> ngAfterViewInit()
(l'initialisation du nœud de vue a lieu après l'initialisation du contenu projeté) 🎜🎜🎜ContentChild
et ViewChild
existent également dans au pluriel, c'est-à-dire ContentChildren et <code>ViewChildren
, ils obtiennent une collection de nœuds, il n'y a pas de différence entre les autres 🎜🎜L'écriture est la suivante : 🎜rrreee🎜Pour pour plus de connaissances liées à la programmation, veuillez visiter : 🎜Introduction à la programmation🎜 ! ! 🎜Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!