Heim  >  Artikel  >  Web-Frontend  >  Ein Artikel zum Verständnis der drei Arten der Inhaltsprojektion in Angular (Single-Slot, Multi-Slot, bedingt)

Ein Artikel zum Verständnis der drei Arten der Inhaltsprojektion in Angular (Single-Slot, Multi-Slot, bedingt)

青灯夜游
青灯夜游nach vorne
2021-10-14 10:42:303246Durchsuche

Dieser Artikel hilft Ihnen, die Inhaltsprojektion in Angular zu verstehen und stellt die Inhaltsprojektion mit einem Slot, die Inhaltsprojektion mit mehreren Slots und die bedingte Inhaltsprojektion vor. Ich hoffe, dass er für alle hilfreich ist!

Ein Artikel zum Verständnis der drei Arten der Inhaltsprojektion in Angular (Single-Slot, Multi-Slot, bedingt)

【Verwandte Tutorial-Empfehlung: „Angular-Tutorial“】

Einzelne Slot-Inhaltsprojektion

Einzelne Slot-Inhaltsprojektion bedeutet, eine Komponente zu erstellen, in die Sie eine Komponente projizieren können.

zippy-basic.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-zippy-basic',
  template: `
  <h2>单插槽内容投影</h2>
  <ng-content></ng-content>
`
})
export class ZippyBasicComponent {}

Mit dem ng-content-Element können Benutzer dieser Komponente nun ihre eigenen Nachrichten in die Komponente projizieren. Zum Beispiel: ng-content 元素,该组件的用户现在可以将自己的消息投影到该组件中。例如:

app.component.html

<!-- 将 app-zippy-basic 元素包裹的全部内容投影到 zippy-basic 组件中去 -->
<app-zippy-basic>
  <p>单插槽内容投影:投影数据</p>
</app-zippy-basic>

效果如下:
Ein Artikel zum Verständnis der drei Arten der Inhaltsprojektion in Angular (Single-Slot, Multi-Slot, bedingt)

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 &#39;@angular/core&#39;;

@Component({
  selector: &#39;app-zippy-multislot&#39;,
  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>

效果如下:
Ein Artikel zum Verständnis der drei Arten der Inhaltsprojektion in Angular (Single-Slot, Multi-Slot, bedingt)

在前面的示例中,只有第二个 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>

效果:

Ein Artikel zum Verständnis der drei Arten der Inhaltsprojektion in Angular (Single-Slot, Multi-Slot, bedingt)

ViewChild和ContentChild

  • ContentChild:与内容子节点有关,操作投影进来的内容;
  • ViewChild:与视图子节点有关,操作自身的视图内容;

ContentChild

在上一部分,我们通过内容投影,让自定义的组件标签能够嵌入html标签或自定义组件标签,那么它如何操作投影进来的内容呢?

首先创建两个组件

/**** part-b.component.ts ****/
import { Component, OnInit,Output} from &#39;@angular/core&#39;;

@Component({
	selector: &#39;app-content-part-b&#39;,
	templateUrl: &#39;./part-b.component.html&#39;,
	styleUrls: [&#39;./part-b.component.scss&#39;]
})

export class PartBComponent implements OnInit {
	constructor() { }
	ngOnInit() { }
	
	public func():void{
		console.log("PartB");
	} 
}
/**** part-a.component.ts ****/
import { Component, OnInit, ContentChild } from &#39;@angular/core&#39;;
// 1、引入 part-b 组件
import { PartBComponent } from &#39;../part-b/part-b.component&#39;;

@Component({
	selector: &#39;app-content-part-a&#39;,
	templateUrl: &#39;./part-a.component.html&#39;,
	styleUrls: [&#39;./part-a.component.scss&#39;]
})

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(&#39;PartA&#39;)
	}
}

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()是与投影内容初始化有关,所以我们有关投影的内容操作尽量放在它初始化完成之后进行

ViewChild

上一部分的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 &#39;@angular/core&#39;;

@Component({
	selector: &#39;app-content&#39;,
	templateUrl: &#39;./content.component.html&#39;,
	styleUrls: [&#39;./content.component.scss&#39;]
})

export class ContentComponent implements OnInit {
	// 2、获取视图 partA
	@ViewChild(&#39;partA&#39;) partA: any;
	constructor() { }
	ngOnInit() {}
	ngAfterViewInit(): void {
		// 3、调用 part-a 组件的 func() 方法
		this.partA.func();
	}
}

ngAfterContentInit()对应的是ngAfterViewInit()(视图节点初始化是在投影内容初始化之后)

ContentChildViewChild还存在复数的形式,即ContentChildrenViewChildren

app.component.html

import { Component, OnInit, ContentChild,ContentChildren ,QueryList } from &#39;@angular/core&#39;;
import { PartBComponent } from &#39;../part-b/part-b.component&#39;;

@Component({
	selector: &#39;app-content-part-a&#39;,
	templateUrl: &#39;./part-a.component.html&#39;,
	styleUrls: [&#39;./part-a.component.scss&#39;]
})
export class PartAComponent implements OnInit {

	@ContentChildren(PartBComponent) PartBs: QueryList<PartBComponent>;

	constructor() { }
	ngOnInit() {}
}

Der Effekt ist wie folgt:
Bildbeschreibung hier einfügen

ng-content-Element ist ein Platzhalter, es erstellt kein echtes DOM-Element. Diese benutzerdefinierten Attribute von ng-content werden ignoriert.

🎜🎜🎜Multi-Slot-Inhaltsprojektion🎜🎜🎜
  • Die Komponentenvorlage enthält mehrere ng-content-Tags.
  • Um den projizierten Inhalt zu unterscheiden, der auf das entsprechende ng-content-Tag projiziert werden kann, müssen Sie selectfür ng verwenden -content tag >Attribut als Identifikation.
  • Das Attribut select unterstützt jede Kombination aus Tag-Namen, Attributen, CSS-Klassen und :not Pseudoklassen.
  • Das Tag ng-content ohne das Hinzufügen des Attributs select wird als Standard-Slot verwendet. Alle passenden projizierten Inhalte werden an der Position des ng-Inhalts projiziert.
🎜🎜zippy-multislot.component.ts🎜rrreee🎜app.component.html🎜rrreee🎜Der Effekt ist wie folgt:
Bildbeschreibung hier einfügen🎜🎜🎜Im vorherigen Beispiel ist nur für das zweite ng-content-Element das select-Attribut definiert. Infolgedessen empfängt das erste ng-content-Element alle anderen in die Komponente projizierten Inhalte. 🎜🎜🎜🎜🎜Bedingte Inhaltsprojektion🎜🎜🎜🎜 Es wird empfohlen, das Tag ng-container zu verwenden, da dieses Tag kein Rendern echter DOM-Elemente erfordert. 🎜🎜rrreee
Parameter Typ Beschreibung
templateRefExp TemplateRef |. null Eine Zeichenfolge, die zum Definieren der Vorlagenreferenz und des Kontextobjekts der Vorlage verwendet wird
contextExp Object |. null ist ein Objekt, dessen Schlüsselname in einer let-Anweisung in einer lokalen Vorlage gebunden werden kann. Wenn $implicit als Schlüsselname in einem Kontextobjekt verwendet wird, wird dieser als Standardwert verwendet.
🎜ng-template-Tags #ID stimmt mit templateRefExp überein, und The Der Inhalt des ng-template-Tags wird in das angegebene ngTemplateOutlet eingebettet. 🎜🎜Example 1: 🎜rrreeeSeffect: 🎜🎜 Ein Artikel zum Verständnis der drei Arten der Inhaltsprojektion in Angular (Single-Slot, Multi-Slot, bedingt)🎜🎜🎜ViewChild und ContentChild🎜🎜
  • ContentChild: bezogen auf den Inhaltsunterknoten, 🎜verwaltet den projizierten Inhalt🎜;
  • ViewChild: Bezogen auf den untergeordneten Ansichtsknoten, 🎜betreibt seinen eigenen Ansichtsinhalt🎜;

🎜ContentChild🎜

🎜Im vorherigen Teil haben wir die Inhaltsprojektion verwendet Damit benutzerdefinierte Komponenten-Tags HTML-Tags oder benutzerdefinierte Komponenten-Tags einbetten können, wie funktioniert es mit dem projizierten Inhalt? 🎜🎜Erstellen Sie zunächst zwei Komponenten.🎜rrreeerrreee🎜Projizieren Sie den Inhalt der part-b-Komponente zur part-a-Komponente 🎜rrreee🎜🎜Im Lebenszyklus der Komponente gibt es einen Hook ngAfterContentInit(), der sich auf die Initialisierung des projizierten Inhalts bezieht, Daher geht es uns um den projizierten Inhalt. Versuchen Sie, die Operation auszuführen, nachdem die Initialisierung abgeschlossen ist. while ViewChild Was funktioniert, ist sein eigener Ansichtsinhalt
Ändern Sie die content.component.html des vorherigen Teils wie folgt: 🎜rrreeerrreee🎜🎜ngAfterContentInit() entspricht <code> ngAfterViewInit() (Die Initialisierung des Ansichtsknotens erfolgt nach der Initialisierung des projizierten Inhalts). 🎜🎜🎜ContentChild und ViewChild sind ebenfalls vorhanden Pluralform, also ContentChildren und <code>ViewChildren, was sie erhalten, ist eine Sammlung von Knoten, es gibt keinen Unterschied zwischen den anderen 🎜🎜Die Schreibweise lautet wie folgt: 🎜rrreee 🎜Weitere Kenntnisse zum Thema Programmierung finden Sie unter: 🎜Einführung in die Programmierung🎜! ! 🎜

Das obige ist der detaillierte Inhalt vonEin Artikel zum Verständnis der drei Arten der Inhaltsprojektion in Angular (Single-Slot, Multi-Slot, bedingt). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen