Home >Web Front-end >JS Tutorial >Let's talk about the method of content projection in angular

Let's talk about the method of content projection in angular

青灯夜游
青灯夜游Original
2022-05-12 10:41:282230browse

This article will talk about content projection in angular, introduce the method of using ng-content for content projection, and understand the implementation method of conditional content projection. I hope it will be helpful to everyone. !

Let's talk about the method of content projection in angular

1. ng-content Content projection

1.1 <span style="font-size: 16px;">ng-content</span>

ng-content element is a placeholder used to insert external or dynamic content symbol. The parent component passes external content to the child component. When Angular parses the template, the external content will be inserted in the child component template where ng-content appears. . [Related tutorial recommendations: "angular tutorial"]

We can use content projection to create reusable components. These components have similar logic and layout and can be used in many places. Generally we often use it when encapsulating some public components.

1.2 Why use content projection

Define a button component:

button-component.ts

@Component({
    selector: &#39;[appButton]&#39;,
    template: `
    <span class="icon-search"></span>
`
})
export class AppButtonComponent {}

The purpose of this button component is to add a search icon inside the button. We actually use it as follows:

<button appButton>click</button>

We found that the component will only display the search icon, and the text of the button will not be displayed. , you may think of the most commonly used @Input decorator, but what if we don’t just want to pass in text, but a paragraph of html? ng-content will be used at this time.

1.3 Single Slot Content Projection

The most basic form of content projection is Single Slot Content Projection.

Single-slot content projection refers to creating a component into which we can project a component.

Take the button component as an example to create a single-slot content projection:

button-component.ts

@Component({
    selector: &#39;[appButton]&#39;,
    template: `
    <span class="icon-search"></span> <ng-content></ng-content>
`
})
export class AppButtonComponent {}

The actual usage is as follows:

<button appButton>click</button>

It can be found that the effect of this button component is to display both the search icon and the text of the button (click). That is, the content in the middle of 2b4ad80bee79097601321f1e5d22b32765281c5ac262bf6d81768915a4a77ac0 is projected to the d553bd28b5bbbbd4b6fb4990edbabbf078e68693bbc3a4be56286441c90e88e6 Location. The

ng-content element is a placeholder, it does not create a real DOM element. Those custom attributes of ng-content will be ignored.

1.4 Multi-slot content projection

A component can have multiple slots, each A slot can specify a CSS selector, which determines what content goes into the slot. This mode is called Multi-Slot Content Projection. Using this mode, we must specify the position where we want the projected content to appear. This can be accomplished by using the select attribute of ng-content.

  • The component template contains multiple ng-content tags.
  • In order to distinguish the projected content that can be projected to the corresponding ng-content tag, you need to use the select attribute on the ng-content tag as identification .
  • select Attributes support tag name, property, CSS class and :not pseudo-class## Any combination of #.
  • A
  • ng-content tag that does not add the select attribute will serve as the default slot. All unmatched projected content will be projected at this ng-content location.
Take the button component as an example to create a multi-slot content projection:

button-component.ts

@Component({
    selector: &#39;[appButton]&#39;,
    template: `
    <span class="icon-search"></span> <ng-content select="[shuxing]"></ng-content> <ng-content select="p"></ng-content> <ng-content select=".lei"></ng-content>
`
})
export class AppButtonComponent {}

The actual usage is as follows:

<button appButton>
<p>click</p> <span shuxing>me</span> <span class="lei">here</span>
</button>

1.5 ngProjectAs<span style="font-size: 16px;"></span>

In some cases, we need to use

ng-container Wrap some content and pass it to the component. Most of the time it's because we need to use structural directives like ngIf or ngSwitch etc. .

In the example below, we wrap

header in ng-container.

@Component({
    selector: &#39;app-card&#39;,
    template: `
		<div class="card">
		  <div class="header">
		    <ng-content select="header"></ng-content>
		  </div>
		  <div class="content">
		    <ng-content select="content"></ng-content>
		  </div>
		  <div class="footer">
		    <ng-content select="footer"></ng-content>
		  </div>
		  <ng-content></ng-content>
		</div>
`
})
export class AppCardComponent {}

Usage:

<app-card>
  <ng-container>
    <header>
      <h1>Angular</h1>
    </header>
  </ng-container>
  <content>One framework. Mobile & desktop.</content>
  <footer><b>Super-powered by Google </b></footer>
</app-card>

Due to the existence of

ng-container, the header part is not rendered into the slot we want to render. , instead it is rendered into ng-content which does not provide any selector. In this case we can use the
ngProjectAs attribute. Add this attribute to
ng-container above, and you can render it according to our expectations.

<app-card>
  <ng-container ngProjectAs=&#39;header&#39;>
    <header>
      <h1>Angular</h1>
    </header>
  </ng-container>
  <content>One framework. Mobile & desktop.</content>
  <footer><b>Super-powered by Google </b></footer>
</app-card>

二、 有条件的内容投影

如果你的元件需要有条件地渲染内容或多次渲染内容,则应配置该元件以接受一个 ng-template 元素,其中包含要有条件渲染的内容。

在这种情况下,不建议使用 ng-content 元素,因为只要元件的使用者提供了内容,即使该元件从未定义 ng-content 元素或该 ng-content 元素位于 ngIf 语句的内部,该内容也总会被初始化。

使用 ng-template 元素,你可以让元件根据你想要的任何条件显式渲染内容,并可以进行多次渲染。在显式渲染 ng-template 元素之前,Angular 不会初始化该元素的内容。

2.1 <span style="font-size: 16px;">ng-container</span>

既不是一个组件,也不是一个指令,仅仅是一个特殊的tag而已。 使用 ng-container 渲染所包含的模板内容,不包含自身。

  • angular代码片段
<div>
  <ng-container>
    <p>My name is wyl.</p>
    <p>What is you name?</p>
  </ng-container>
</div>
  • 浏览器调试窗口,可以发现 d4a8107efa96305af677e1edd4999c73 标签消失了,并没有起任何作用
<div>
  <p>My name is wyl.</p>
  <p>What is you name?</p>
</div>
  • 使用场景,如下,在我们需要遍历if 判断 时,它可以承担一个载体的作用
<ul>
  <ng-container *ngFor="let item of items">
    <li>{{ item .name}}</li>
    <li>{{ item .age}}</li>
    <li>{{ item .sex}}</li>
  </ng-container>
</ul>

另外,ng 中常见错误之一的 forif 不能写在同一标签上(在一个宿主元素上只能应用一个结构型指令),利用 ng-container 标签可以在实现功能的基础上减少层级的嵌套。

2.2 <span style="font-size: 16px;">ng-template</span>

先来看下面一段代码

<ng-template>
    <p> In template, no attributes. </p>
</ng-template>

<ng-container>
    <p> In ng-container, no attributes. </p>
</ng-container>

浏览器输出结果是:

In ng-container, no attributes.

6efee24582b35a5bc3ecd0628f23f6da 中的内容不会显示。当在上面的模板中添加 ngIf 指令:

<ng-template [ngIf]="true">
   <p> ngIf with a ng-template.</p>
</ng-template>

<ng-container *ngIf="true">
   <p> ngIf with an ng-container.</p>
</ng-container>

浏览器输出结果是:

ngIf with a ng-template.
ngIf with an ng-container.

2.3 <span style="font-size: 16px;">ng-template</span><span style="font-size: 16px;">d4a8107efa96305af677e1edd4999c73</span> 的配合使用

<ng-container *ngIf="showSearchBread; else tplSearchEmpty">
     暂时搜索不到您要的数据喔
</ng-container>
<ng-template #tplSearchEmpty>
     快快开始获取吧!
</ng-template>

2.4 <span style="font-size: 16px;">ngTemplateOutlet</span>

插入 ng-template 创建的内嵌视图。 ngTemplateOutlet 是一个结构型指令,接收一个 TemplateRef 类型的值;

<div *ngTemplateOutlet="tpl1"></div>
<ng-template #tpl1>
  <span>I am span in template {{title}}</span>
</ng-template>

*ngTemplateOutlet = "templateRefExp; content: contentExp "

  • templateRefExp: ng-template 元素的 #ID
  • contextExp:
    • 可空参数

    • content 是一个对象,这个对象可以包含一个 $implicitkey 作为默认值, 使用时在 模板 中用 let-key 语句进行绑定

    • content 的非默认字段需要使用 let-templateKey=contentKey 语句进行绑定

使用如下:

@Component({
  selector: &#39;ng-template-outlet-example&#39;,
  template: `
    <ng-container *ngTemplateOutlet="greet"></ng-container>
    <hr>
    <ng-container *ngTemplateOutlet="eng; context: myContext"></ng-container>
    <hr>
    <ng-container *ngTemplateOutlet="svk; context: myContext"></ng-container>
    <hr>
    <ng-template #greet><span>Hello</span></ng-template>
    <ng-template #eng let-name><span>Hello {{name}}!</span></ng-template>
    <ng-template #svk let-person="localSk"><span>Ahoj {{person}}!</span></ng-template>
`
})
class NgTemplateOutletExample {
  myContext = {$implicit: &#39;World&#39;, localSk: &#39;Svet&#39;};
}

2.5 利用 <span style="font-size: 16px;">ngTemplateOutlet</span> 进行内容投影

@Component({
    selector: &#39;app-card&#39;,
    template: `
		<div class="card">
		  <div class="header">
		  	<ng-container *ngTemplateOutlet="headerTemplate; context: { $implicit: title, index: otherDate }"></ng-container>
		  </div>
		</div>
`
})
export class AppCardComponent {

	@ContentChild(&#39;header&#39;, { static: true }) headerTemplate: TemplateRef<any>;

	public title = &#39;Test&#39;;
	public otherDate = {
	 	auth: &#39;me&#39;,
	 	name: &#39;appCard&#39;
	};
}

使用

<app-card>
  <ng-template #header let-label let-item="otherDate">
    <h1>Angular</h1> {{label}} (Test) and  {{otherDate | json}} ({auth: &#39;me&#39;, name: &#39;appCard&#39;})
  </ng-template>
</app-card>

更多编程相关知识,请访问:编程教学!!

The above is the detailed content of Let's talk about the method of content projection in angular. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn