有这么个需求,页面可以定制项目中的组件,不同的人显示的组件不一样,每个组件是个独立的页面,而不是通过路由跳转的单页面,也就是一个页面上显示多个动态子组件组成的页面。这时候,用angular的动态组件就可以解决问题,实现方案如下(部分代码直接拷贝angular中文文档):
一、创建指令
src/app/ad.directive.ts
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[ad-host]',
})
export class AdDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
二、加载组件
rc/app/ad-banner.component.ts (template)
template: `
<div class="ad-banner-example">
<h3>Advertisements</h3>
<ng-template ad-host></ng-template>
</div>
`
三、解析组件(关键步骤)
rc/app/main.component.ts
@ViewChild(WidgetDirective) widgetHost: WidgetDirective;
userWPojos: any = [];
ws: any = [];
constructor(private wService: WService,
private componentFactoryResolver: ComponentFactoryResolver) {
}
ngOnInit() {
this.getData();
}
/**
*获取当前用户所拥有的组件(页面)的方法(业务需求)
*/
getData() {
this.wService.getData().subscribe(
data => {
this.userWPojos = data['resultValue']['userWPojos'];
for (const userW of this.userWPojos) {
this.ws = [...this.ws, new WItem(userW.component, userW)];
}
this.loadComponent();
});
}
loadComponent() {
const viewContainerRef = this.widgetHost.viewContainerRef;
viewContainerRef.clear();
for (const w of this.ws) {
// 通过componentMap将组件名字转换为组件Type类型
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentMap[w.component].prototype.constructor);
const componentRef = viewContainerRef.createComponent(componentFactory);
// 所有动态组件都要实现的接口 WComponent,WComponent只有一个data属性
(<WComponent>componentRef.instance).data = w.data;
}
}
四、其他代码
componentMap.ts
import {SComponent} from "../components/resource/s/s.component";
import {HComponent} from "../components/resource/h/h.component";
import {BComponent} from "../components/system/b/b.component";
/**
* Created by ... on ...
* 用于组件字符串名称转化为Type类
*/
export const componentMap = {
SComponent: SComponent,
HComponent: HComponent,
BComponent: BComponent,
};