angular使用动态组件后属性值_Angular - 动态组件加载器

动态组件加载器link

Dynamic component loaderlink

译注:本页讲的是一个用于显示广告的范例,而部分广告拦截器插件,比如 Chrome 的 AdGuard,可能会破坏其工作逻辑,因此,请在本页关闭那些插件。

组件的模板不会永远是固定的。应用可能会需要在运行期间加载一些新的组件。

Component templates are not always fixed. An application may need to load new components at runtime.

This cookbook shows you how to use

See the

动态组件加载link

Dynamic component loadinglink

下面的例子展示了如何构建动态广告条。

The following example shows how to build a dynamic ad banner.

英雄管理局正在计划一个广告活动,要在广告条中显示一系列不同的广告。几个不同的小组可能会频繁加入新的广告组件。 再用只支持静态组件结构的模板显然是不现实的。

The hero agency is planning an ad campaign with several different ads cycling through the banner. New ad components are added frequently by several different teams. This makes it impractical to use a template with a static component structure.

你需要一种新的组件加载方式,它不需要在广告条组件的模板中引用固定的组件。

Instead, you need a way to load a new component without a fixed reference to the component in the ad banner's template.

Angular 自带的 API 就能支持动态加载组件。

Angular comes with its own API for loading components dynamically.

The anchor directivelink

在添加组件之前,先要定义一个锚点来告诉 Angular 要把组件插入到什么地方。

Before you can add components you have to define an anchor point to tell Angular where to insert components.

广告条使用一个名叫 AdDirective 的辅助指令来在模板中标记出有效的插入点。

The ad banner uses a helper directive called AdDirective to mark valid insertion points in the template.import { Directive, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[adHost]', }) export class AdDirective { constructor(public viewContainerRef: ViewContainerRef) { } }src/app/ad.directive.tscontent_copy

import{Directive,ViewContainerRef}from'@angular/core';@Directive({selector:'[adHost]',})exportclassAdDirective{constructor(publicviewContainerRef:ViewContainerRef){}}

AdDirective 注入了

AdDirective injects

在 ad-host,它就是你将应用到元素上的指令。下一节会展示该如何做。

In the adHost; that's what you use to apply the directive to the element. The next section shows you how.

加载组件link

Loading componentslink

广告条的大部分实现代码都在 ad-banner.component.ts 中。 为了让这个例子简单点,HTML 被直接放在了 template 属性中。

Most of the ad banner implementation is in ad-banner.component.ts. To keep things simple in this example, the HTML is in the template property as a template string.

元素就是刚才制作的指令将应用到的地方。 要应用 AdDirective,回忆一下来自 ad.directive.ts 的选择器 ad-host。把它应用到 (不用带方括号)。 这下,Angular 就知道该把组件动态加载到哪里了。

The element is where you apply the directive you just made. To apply the AdDirective, recall the selector from ad.directive.ts, [adHost]. Apply that to without the square brackets. Now Angular knows where to dynamically load components.template: `

Advertisements

`src/app/ad-banner.component.ts (template)content_copy

template:`

Advertisements

`

元素是动态加载组件的最佳选择,因为它不会渲染任何额外的输出。

The element is a good choice for dynamic components because it doesn't render any additional output.

解析组件link

Resolving componentslink

深入看看 ad-banner.component.ts 中的方法。

Take a closer look at the methods in ad-banner.component.ts.

AdBannerComponent 接收一个 AdItem 对象的数组作为输入,它最终来自 AdService。 AdItem 对象指定要加载的组件类,以及绑定到该组件上的任意数据。 AdService 可以返回广告活动中的那些广告。

AdBannerComponent takes an array of AdItem objects as input, which ultimately comes from AdService. AdItem objects specify the type of component to load and any data to bind to the component.AdService returns the actual ads making up the ad campaign.

给 AdBannerComponent 传入一个组件数组可以在模板中放入一个广告的动态列表,而不用写死在模板中。

Passing an array of components to AdBannerComponent allows for a dynamic list of ads without static elements in the template.

通过 getAds() 方法,AdBannerComponent 可以循环遍历 AdItems 的数组,并且每三秒调用一次 loadComponent() 来加载新组件。

With its getAds() method, AdBannerComponent cycles through the array of AdItems and loads a new component every 3 seconds by calling loadComponent().export class AdBannerComponent implements OnInit, OnDestroy { @Input() ads: AdItem[]; currentAdIndex = -1; @ViewChild(AdDirective, {static: true}) adHost: AdDirective; interval: any; constructor(private componentFactoryResolver: ComponentFactoryResolver) { } ngOnInit() { this.loadComponent(); this.getAds(); } ngOnDestroy() { clearInterval(this.interval); } loadComponent() { this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length; const adItem = this.ads[this.currentAdIndex]; const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component); const viewContainerRef = this.adHost.viewContainerRef; viewContainerRef.clear(); const componentRef = viewContainerRef.createComponent(componentFactory); componentRef.instance.data = adItem.data; } getAds() { this.interval = setInterval(() => { this.loadComponent(); }, 3000); } }src/app/ad-banner.component.ts (excerpt)content_copy

exportclassAdBannerComponentimplementsOnInit,OnDestroy{@Input()ads:AdItem[];currentAdIndex=-1;@ViewChild(AdDirective,{static:true})adHost:AdDirective;interval:any;constructor(privatecomponentFactoryResolver:ComponentFactoryResolver){}ngOnInit(){this.loadComponent();this.getAds();}ngOnDestroy(){clearInterval(this.interval);}loadComponent(){this.currentAdIndex=(this.currentAdIndex+1)%this.ads.length;constadItem=this.ads[this.currentAdIndex];constcomponentFactory=this.componentFactoryResolver.resolveComponentFactory(adItem.component);constviewContainerRef=this.adHost.viewContainerRef;viewContainerRef.clear();constcomponentRef=viewContainerRef.createComponent(componentFactory);componentRef.instance.data=adItem.data;}getAds(){this.interval=setInterval(()=>{this.loadComponent();},3000);}}

这里的 loadComponent() 方法很重要。 来一步步看看。首先,它选取了一个广告。

The loadComponent() method is doing a lot of the heavy lifting here. Take it step by step. First, it picks an ad.

loadComponent() 如何选择广告

How loadComponent() chooses an ad

loadComponent() 方法使用某种算法选择了一个广告。

The loadComponent() method chooses an ad using some math.

(译注:循环选取算法)首先,它把 currentAdIndex 递增一,然后用它除以 AdItem 数组长度的余数作为新的 currentAdIndex 的值, 最后用这个值来从数组中选取一个 adItem。

First, it sets the currentAdIndex by taking whatever it currently is plus one, dividing that by the length of the AdItem array, and using the remainder as the new currentAdIndex value. Then, it uses that value to select an adItem from the array.

在 loadComponent() 选取了一个广告之后,它使用

After loadComponent() selects an ad, it uses

接下来,你要把 viewContainerRef 指向这个组件的现有实例。但你怎么才能找到这个实例呢? 很简单,因为它指向了 adHost,而这个 adHost 就是你以前设置过的指令,用来告诉 Angular 该把动态组件插入到什么位置。

Next, you're targeting the viewContainerRef that exists on this specific instance of the component. How do you know it's this specific instance? Because it's referring to adHost and adHost is the directive you set up earlier to tell Angular where to insert dynamic components.

回忆一下,AdDirective 曾在它的构造函数中注入了一个

As you may recall, AdDirective injects

要把这个组件添加到模板中,你可以调用 createComponent()。

To add the component to the template, you call createComponent() on

createComponent() 方法返回一个引用,指向这个刚刚加载的组件。 使用这个引用就可以与该组件进行交互,比如设置它的属性或调用它的方法。

The createComponent() method returns a reference to the loaded component. Use that reference to interact with the component by assigning to its properties or calling its methods.

公共的 AdComponent 接口link

The AdComponent interfacelink

在广告条中,所有组件都实现了一个公共接口 AdComponent,它定义了一个标准化的 API,来把数据传给组件。

In the ad banner, all components implement a common AdComponent interface to standardize the API for passing data to the components.

下面就是两个范例组件及其 AdComponent 接口:

Here are two sample components and the AdComponent interface for reference:import { Component, Input } from '@angular/core'; import { AdComponent } from './ad.component'; @Component({ template: `

{{data.headline}}
{{data.body}}
` }) export class HeroJobAdComponent implements AdComponent { @Input() data: any; }import { Component, Input } from '@angular/core'; import { AdComponent } from './ad.component'; @Component({ template: `

Featured Hero Profile

{{data.name}}

{{data.bio}}

Hire this hero today!
` }) export class HeroProfileComponent implements AdComponent { @Input() data: any; }export interface AdComponent { data: any; }hero-job-ad.component.ts

hero-profile.component.ts

ad.component.ts

content_copy

import{Component,Input}from'@angular/core';import{AdComponent}from'./ad.component';@Component({template:`

{{data.headline}}

{{data.body}}

`})exportclassHeroJobAdComponentimplementsAdComponent{@Input()data:any;}

最终的广告栏link

Final ad bannerlink

最终的广告栏是这样的:

The final ad banner looks like this:

See the

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值