1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > angular使用动态组件后属性值_Angular5.x动态加载组件

angular使用动态组件后属性值_Angular5.x动态加载组件

时间:2019-03-26 11:47:36

相关推荐

angular使用动态组件后属性值_Angular5.x动态加载组件

Angular5.x动态加载组件

前言

在我们利用Angular进行开发的时候,会碰到这一样的一个场景,随着业务的不断扩大,页面里面的组件、modal、popup、越来越多的时候,页面占用的开销就越大,但是很多组件虽然初始化了,但是确只有在点击的时候才会使用到。

为了解决这种情况,因而考虑用动态创建组件的方式来加载和使用组件。

1、未优化前的页面组件情况

这边以项目中碰到的例子举例,场景是用户管理下有一大堆用户操作弹窗组件,分别在ponent.html

和table-ponent.html 下,table-items为users下的子组件,用来显示用户数据。

由上面数据来看,一个用户管理列表下的组件就达到20几个,当我们用户数据量多的时候,渲染起来导致的卡顿是非常严重的,但是很多组件确并不是一直被使用的。之后在某一些操作之后才会使用到。

2、优化后的页面组件情况

可以看到,我们将所有的组件初始化在页面中去除,只留下一个动态容器,用来存放到时候创建的组件位置。

1、创建ViewContainerRef,用来存放视图容器。

import { ViewContainerRef, ViewChild } from '@angular/core';

export class TableItemsComponent {

// 这边需要利用@ViewChild去获取视图容器,这边有两个参数,第一个参数是容器名或者组件名,第二个参数如果不添加就表示直接获取组件或者元素。

@ViewChild('componentContainer', { read: ViewContainerRef })

public componentContainer: ViewContainerRef

}

2、使用ComponentFactoryResolver创建ComponentFactory组件工厂。

import { ViewContainerRef, ViewChild, ComponentFactoryResolver } from '@angular/core';

export class TableItemsComponent {

// 这边需要利用@ViewChild去获取视图容器,这边有两个参数,第一个参数是容器名或者组件名,第二个参数如果不添加就表示直接获取组件或者元素。

@ViewChild('componentContainer', { read: ViewContainerRef })

public componentContainer: ViewContainerRef;

constructor(

public resolver: ComponentFactoryResolver

) {}

// 创建组件方法

public createComponent() {

// 调用ComponentFactoryResolver中的resolveComponentFactory函数,这个函数会返回一个ComponentFactory对象,如下一段TS代码所示

const factory = this.resolver.resolveComponentFactory(Component);

}

}

// class ComponentFactoryResolver

export declare abstract class ComponentFactoryResolver {

static NULL: ComponentFactoryResolver;

abstract resolveComponentFactory(component: Type): ComponentFactory;

}

3、利用ViewContainerRef创建组件引用

import { ViewContainerRef, ViewChild, ComponentFactoryResolver } from '@angular/core';

export class TableItemsComponent {

constructor(

public resolver: ComponentFactoryResolver

) {}

@ViewChild('componentContainer', { read: ViewContainerRef })

public componentContainer: ViewContainerRef

public createComponent() {

const factory = this.resolver.resolveComponentFactory(Component);

// 调用ViewContainerRef中的createComponent方法,这个方法会返回一个组件引用,如下一段TS代码所示

const componentRef = ponentContainer.createComponent(factory);

}

}

export declare abstract class ViewContainerRef {

/**

* Instantiates a single {@link Component} and inserts its Host View into this container at the

* specified `index`.

*

* The component is instantiated using its {@link ComponentFactory} which can be obtained via

* {@link ComponentFactoryResolver#resolveComponentFactory resolveComponentFactory}.

*

* If `index` is not specified, the new View will be inserted as the last View in the container.

*

* You can optionally specify the {@link Injector} that will be used as parent for the Component.

*

* Returns the {@link ComponentRef} of the Host View created for the newly instantiated Component.

*/

abstract createComponent(componentFactory: ComponentFactory, index?: number, injector?: Injector, projectableNodes?: any[][], ngModule?: NgModuleRef): ComponentRef;

}

4、组合起来创建组件实例

import { ViewContainerRef, ViewChild, ComponentFactoryResolver } from '@angular/core';

// 组件导入

import { AddTagsDialogComponent } from '../add-tags-dialog/add-tags-ponent';

import { AddGroupsDialogComponent } from '../add-groups-dialog/add-groups-ponent';

import { TopUpDialogComponent } from '../top-up-dialog/top-up-ponent';

import { GiveVipDialogComponent } from '../give-vip-dialog/give-vip-ponent';

import { GiveVipCouponComponent } from '../give-coupon-dialog/give-coupon-ponent';

import { StateUpdateDialogComponent } from '../state-update-dialog/state-update-ponent';

import { UserIntegralDialogComponent } from '../user-integral-dialog/user-integral-ponent';

import { BalanceDialogComponent } from '../balance-dialog/balance-ponent';

import { IntegralDialogComponent } from '../integral-dialog/integral-ponent';

import { ConsumeDialogComponent } from '../consume-dialog/consume-ponent';

import { UserAllExportDialogComponent } from '../user-all-export-dialog/user-all-export-ponent';

import { UpdateRoleDialogComponent } from '../update-role-dialog/update-role-ponent';

import { CouponDetailComponent } from '../coupon-detail-dialog/coupon-detail-ponent';

import { TimesCardDialogComponent } from '../times-card-dialog/times-card-ponent';

import { AllotGuideDialogComponent } from '../allot-guide-dialog/allot-guide-ponent';

import { IncreaseTagsComponent } from '../increase-tags/increase-ponent';

export class TableItemsComponent {

@ViewChild('componentContainer', { read: ViewContainerRef })

public componentContainer: ViewContainerRef

constructor(

public resolver: ComponentFactoryResolver

) {}

// 以下只是个人的一些实现,并不算太好,这边参考就好,主要提供一个思路。

/**

* @desc 创建组件

* @param {string} type - 组件名

*/

public createComponent(type: string): any {

// 清空容器

ponentContainer.clear();

const COMPONENT_OBJ = {

addTagsDialog: {

instance: AddTagsDialogComponent,

input: [],

output: []

},

addGroupsDialog: {

instance: AddGroupsDialogComponent,

input: [],

output: []

},

topUpDialog: {

instance: TopUpDialogComponent,

input: [],

output: []

},

giveVipDialog: {

instance: GiveVipDialogComponent,

input: [],

output: []

},

giveCouponDialog: {

instance: GiveVipCouponComponent,

input: [],

output: []

},

stateUpdateDialog: {

instance: StateUpdateDialogComponent,

input: [],

output: [{

origin: 'onSubmit',

callFn: this.refreshData

}]

},

userIntegralDialog: {

instance: UserIntegralDialogComponent,

input: [{

origin: 'userList',

to: this.tableItemsService.userList

}],

output: []

},

balanceDialog: {

instance: BalanceDialogComponent,

input: [],

output: [{

origin: 'showDialog',

callFn: this.showTopDialog

}]

},

integralDialog: {

instance: IntegralDialogComponent,

input: [],

output: [{

origin: 'showDialog',

callFn: this.showIntegralDialog

}]

},

consumeDialog: {

instance: ConsumeDialogComponent,

input: [],

output: []

},

userAllExportDialog: {

instance: UserAllExportDialogComponent,

input: [],

output: []

},

updateRoleDialog: {

instance: UpdateRoleDialogComponent,

input: [],

output: []

},

couponDetailDialog: {

instance: CouponDetailComponent,

input: [],

output: [{

origin: 'showGiveDialog',

callFn: this.showGiveCouponDialog

}]

},

timesCardDialog: {

instance: TimesCardDialogComponent,

input: [],

output: [{

origin: 'showGiveDialog',

callFn: this.showGiveCouponDialog

}]

},

allotGuideDialog: {

instance: AllotGuideDialogComponent,

input: [],

output: [{

origin: 'onChange',

callFn: this.tableItemsService.getUserList

}]

},

increaseTags: {

instance: IncreaseTagsComponent,

input: [],

output: [{

origin: 'onSaveSuccess',

callFn: this.refreshData

}]

}

}[type];

const factory = this.resolver.resolveComponentFactory(COMPONENT_OBJ.instance);

const componentRef = ponentContainer.createComponent(factory);

// @Input 输入属性处理

if (COMPONENT_OBJ['input'].length) {

COMPONENT_OBJ['input'].forEach((item: any) => {

componentRef.instance[item.origin] = item.to;

});

}

// @Output 输出方法处理

if (COMPONENT_OBJ['output'].length) {

COMPONENT_OBJ['output'].forEach((item: any) => {

componentRef.instance[item.origin].subscribe(($event: any) => {

item.callFn.bind(this)($event); // bind解决this指向问题

});

});

}

// 返回组件实例

return componentRef.instance;

}

}

5、NgModule添加entryComponents

@NgModule({

entryComponents: [

NewUserPopupComponent,

UserDetailPopupComponent,

UpdateSuperiorComponent,

GoodsPurchasesDialogComponent,

CustomShowColumnComponent,

TagsManagementComponent,

TagsChooseDialogComponent,

AddTagsDialogComponent,

AddGroupsDialogComponent,

TopUpDialogComponent,

GiveVipDialogComponent,

GiveVipCouponComponent,

StateUpdateDialogComponent,

UserIntegralDialogComponent,

BalanceDialogComponent,

IntegralDialogComponent,

ConsumeDialogComponent,

UserAllExportDialogComponent,

UpdateRoleDialogComponent,

CouponDetailComponent,

TimesCardDialogComponent,

AllotGuideDialogComponent,

IncreaseTagsComponent

]

})

6、创建并且动态生成组件再调用,减少页面开销

赠送优惠券

3、总结

通过ViewContainerRef创建容器视图。

使用ComponentFactoryResolver创建ComponentFactory组件工厂。

利用ViewContainerRef.createComponent创建组件引用,通过instance引用组件实例。

通过动态组件组件,在视图容器中每次只存在一个组件,每次点击生成组件的时候才在容器里面插入组件,并不是一开始就把所有的组件渲染之后等着调用。这样大大的提升了页面加载的速度和使用的性能。

但是要注意的是,通过这样方式动态生成的组件,Input是不会随着OnChanges监听输入属性和的生命周期去检测输入属性变化的,因此在使用这种动态组件的时候,要考虑组件是否有经常变动的Input,在变动的时候要手动去更新里面的值。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。