内容简介:Angular动态加载组件
引言
有时候需要根据URL来渲染不同组件,我所指的是在同一个URL地址中根据参数的变化显示不同的组件;这是利用Angular动态加载组件完成的,同时也会设法让这部分动态组件也支持AOT。
动态加载组件
下面以一个Step组件为示例,完成一个3个步骤的示例展示,并且可以通过URL user?step=step-one
的变化显示第N个步骤的内容。
1、resolveComponentFactory
首先,还是需要先创建动态加载组件模块。
import { Component, Input, ViewContainerRef, ComponentFactoryResolver, OnDestroy, ComponentRef } from '@angular/core';
@Component({
selector: 'step',
template: ``
})
export class Step implements OnDestroy {
private currentComponent: ComponentRef<any>;
constructor(private vcr: ViewContainerRef, private cfr: ComponentFactoryResolver) {}
@Input() set data(data: { component: any, inputs?: { [key: string]: any } } ) {
const compFactory = this.cfr.resolveComponentFactory(data.component);
const component = this.vcr.createComponent(compFactory);
if (data.inputs) {
for (let key in data.inputs) {
component.instance[key] = data.inputs[key];
}
}
this.destroy();
this.currentComponent = component;
}
destroy() {
if (this.currentComponent) {
this.currentComponent.destroy();
this.currentComponent = null;
}
}
ngOnDestroy(): void {
this.destroy();
}
}
抛开一销毁动作不谈的话,实际就两行代码:
let compFactory = this.cfr.resolveComponentFactory(this.comp);
利用 ComponentFactoryResolver
查找提供组件的 ComponentFactory
,而后利用这个工厂来创建实际的组件。
this.compInstance = this.vcr.createComponent(compFactory);
这一切都非常简单。
而对于一些基本的参数,是直接对组件实例进行赋值。
for (let key in data.inputs) {
component.instance[key] = data.inputs[key];
}
最后,还需要告诉Angular AOT编译器为用户动态组件提供工厂注册,否则 ComponentFactoryResolver
会找不到它们,最简单就是利用 NgModule.entryComponents
进行注册。
@NgModule({
entryComponents: [ UserOneComponent, UserTwoComponent, UserThirdComponent ]
})
export class AppModule { }
但这样其实还是挺奇怪的, entryComponents
本身可能还会存在其他组件。而动态加载组件本身是一个通用性非常强,因此,把它封装成名曰 StepModule
挺有必要的,这样的话,就可以创建一种看起来更舒服的方式。
@NgModule({
declarations: [ Step ],
exports: [ Step ]
})
export class StepModule {
static withComponents(components: any) {
return {
ngModule: StepModule,
providers: [
{ provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: components, multi: true }
]
}
}
}
通过利用 ANALYZE_FOR_ENTRY_COMPONENTS
将多个组件以更友好的方式动态注册至 entryComponents
。
const COMPONENTS = [ ];
@NgModule({
declarations: [ ...COMPONENTS ],
imports: [
StepModule.withComponents([ ...COMPONENTS ])
]
})
export class AppModule { }
2、一个示例
有3个Step步骤的组件,分别为:
// user-one.component.ts
import { Component, OnDestroy, Input, Injector, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'step-one',
template: `<h2>Step One Component:params value: {{step}}</h2>`
})
export class UserOneComponent implements OnDestroy {
private _step: string;
@Input()
set step(str: string) {
console.log('@Input step: ' + str);
this._step = str;
}
get step() {
return this._step;
}
ngOnInit() {
console.log('step one init');
}
ngOnDestroy(): void {
console.log('step one destroy');
}
}
user-two、user-third 略同,这里组件还需要进行注册:
const STEPCOMPONENTS = [ UserOneComponent, UserTwoComponent, UserThirdComponent ];
@NgModule({
declarations: [ ...STEPCOMPONENTS ],
imports: [
StepModule.withComponents([ ...STEPCOMPONENTS ])
]
})
export class AppModule { }
这里没有 entryComponents
字眼,而是为 StepModule
模块帮助我们动态注册。这样至少看起来更内聚一点,而且并不会与其他 entryComponents
在一起,待东西越多越不舒服。
最后,还需要 UserComponent
组件来维护步骤容器,会根据 URL 参数的变化,利用 StepComponent
组件动态加载相应组件。
@Component({
selector: 'user',
template: `<step [comp]="stepComp"></step>`
})
export class UserComponent {
constructor(private route: ActivatedRoute) {}
stepComp: any;
ngOnInit() {
this.route.queryParams.subscribe(params => {
const step = params['step'] || 'step-one';
// 组件与参数对应表
const compMaps = {
'step-one': { component: UserOneComponent, inputs: { step: step } },
'step-two': { component: UserTwoComponent },
'step-third': { component: UserThirdComponent },
};
this.stepComp = compMaps[step];
});
}
}
非常简单的使用,而且又对AOT比较友好。
总结
文章里面一直都在提AOT,其实AOT是Angular为了提供速度与包大小而生的,按我们项目的经验来看至少在包的大小可以减少到 40% 以上。
当然,如果你是用angular cli开发,那么,当你进行 ng build --prod
的时候,默认就已经开启 AOT 编译模式。
以上所述就是小编给大家介绍的《Angular动态加载组件》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- [译] React 16.6 懒加载(与预加载)组件
- Vue异步组件处理路由组件加载状态
- 手把手实现图片懒加载+封装vue懒加载组件
- vue 页面加载进度条组件实例
- dva中组件的懒加载
- Angular4 动态加载组件杂谈
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Learn Python the Hard Way
Zed A. Shaw / Addison-Wesley Professional / 2013-10-11 / USD 39.99
Master Python and become a programmer-even if you never thought you could! This breakthrough book and CD can help practically anyone get started in programming. It's called "The Hard Way," but it's re......一起来看看 《Learn Python the Hard Way》 这本书的介绍吧!