ng-content 中隐藏的内容
如果你尝试在 Angular 中编写可重复使用的组件,则可能会接触到内容投射的概念。然后你发现了 接下来我们来通过一个简单的示例,一步步介绍 Simple example在本文中我们使用一个示例,来演示不同的方式实现内容投影。由于许多问题与Angular 中的组件生命周期相关,因此我们的主要组件将显示一个计数器,用于展示它已被实例化的次数: import { Component } from '@angular/core'; let instances = 0; @Component({ selector: 'counter',template: '<h1>{{this.id}}</h1>' }) class Counter { id: number; constructor() { this.id = ++instances; } } 上面示例中我们定义了 Counter 组件,组件类中的 id 属性用于显示本组件被实例化的次数。接着我们继续定义一个 Wrapper 组件: import { Component } from '@angular/core'; @Component({ selector: 'wrapper',template: ` <div class="box"> <ng-content></ng-content> </div> ` }) class Wrapper {} 现在我们来验证一下效果: <wrapper> <counter></counter> <counter></counter> <counter></counter> </wrapper> Targeted projection有时你希望将包装器的不同子项投影到模板的不同部分。为了处理这个问题, import { Component } from '@angular/core'; @Component({ selector: 'wrapper',template: ` <div class="box red"> <ng-content></ng-content> </div> <div class="box blue"> <ng-content select="counter"></ng-content> </div> `,styles: [` .red {background: red;} .blue {background: blue;} `] }) export class Wrapper { } 上面示例中,我们引入了 <wrapper> <span>This is not a counter</span> <counter></counter> </wrapper> 上述代码成功运行后, ngProjectAs有时你的内部组件会被隐藏在另一个更大的组件中。有时你只需要将其包装在额外的容器中即可应用 <wrapper> <ng-container> <counter></counter> </ng-container> </wrapper> 现在我们的 couter 组件会被投影到第一个红色框中。因为 <wrapper> <ng-container ngProjectAs="counter"> <counter></counter> </ng-container> </wrapper> 通过设置 Time to poke and prod我们从一个简单的实验开始:将两个 页面中会显示一个或两个框,如果我们包含两个框,它们的内容是显示 1 和 1 或 1 和 2? <div class="box red"> <ng-content></ng-content> </div> <div class="box blue"> <ng-content></ng-content> </div> 答案是我们在最后一个 import { Component } from '@angular/core'; @Component({ selector: 'wrapper',template: ` <button (click)="show = !show"> {{ show ? 'Hide' : 'Show' }} </button> <div class="box" *ngIf="show"> <ng-content></ng-content> </div> ` }) class Wrapper { show = true; } 乍一看,似乎正常运行。但是如果你通过按钮进行切换操作,你会注意到计数器的值不会增加。这意味着我们的计数器组件只被实例化了一次 - 从未被销毁和重新创建。难道这是 import { Component } from '@angular/core'; @Component({ selector: 'wrapper',template: ` <div class="box" *ngFor="let item of items"> <ng-content></ng-content> </div> ` }) class Wrapper { items = [0,0]; } 以上代码运行后与我们使用多个 The explanation
这种行为有两个原因:期望一致性和性能。什么 "期望的一致性" 意味着作为开发人员,可以基于应用程序的代码,猜测其行为。假设我写了以下代码: <div class="my-wrapper"> <counter></counter> </div> 很显然计数器将被实例化一次,但现在假如我们使用第三方库的组件: <third-party-wrapper> <counter></counter> </third-party-wrapper> 如果第三方库能够控制 counter 组件的生命周期,我将无法知道它被实例化了多少次。其中唯一方法就是查看第三方库的代码,了解它们的内部处理逻辑。将组件的生命周期被绑定到我们的应用程序组件而不是包装器的意义是,开发者可以掌控计数器只被实例化一次,而不用了解第三方库的内部代码。 性能的原因更为重要。因为 The solution为了让包装器能够控制其子元素的实例化,我们可以通过两种方式完成:在我们的内容周围使用 <wrapper> <ng-template> <counter></counter> </ng-template> </wrapper> 包装器不再使用 @Component({ selector: 'wrapper',template: ` <button (click)="show = !show"> {{ show ? 'Hide' : 'Show' }} </button> <div class="box" *ngIf="show"> <ng-container [ngTemplateOutlet]="template"></ng-container> </div> ` }) class Wrapper { show = true; @ContentChild(TemplateRef) template: TemplateRef; } 现在我们的 counter 组件,每当我们隐藏并重新显示时都正确递增!让我们再验证一下 @Component({ selector: 'wrapper',template: ` <div class="box" *ngFor="let item of items"> <ng-container [ngTemplateOutlet]="template"></ng-container> </div> ` }) class Wrapper { items = [0,0]; @ContentChild(TemplateRef) template: TemplateRef; } 上面代码成功运行后,每个盒子中有一个计数器,显示 1,2 和 3,这正是我们之前预期的结果。 参考资源
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |