A. *_*nis 3 angular-components angular angular7
我想创建一个角度为7(前端)的Web应用程序,以动态加载不同类型的组件,例如本例 https://angular.io/guide/dynamic-component-loader
但是我不确定使用它是否是个好主意ComponentFactoryResolver。我从没用过,也不知道它是否稳定以及性能如何。
如果您知道替代方案,我希望您对此有意见。我不想用native innerHTML
我正在尝试创建具有动态步骤的自定义和通用向导。这个向导有
这些步骤是动态的。根据某些业务逻辑,可以弹出或删除先前步骤中用户输入的内容
我目前的实现方式如下,
我将仅向您展示我正在使用的部分,以使ComponentFactoryResolver您更容易理解和理解:)
export class WizComponent implements OnInit {
public wizContentItems: WizContentItem[] = undefined;
public currentContentItem: WizContentItem = undefined;
public currentContentItemNumber: number = -1;
public currentWizContentComponent: WizContentComponent = undefined;
private componentRef: any;
@Output() public onStepChanged = new EventEmitter<StepPosition>();
private _position: StepPosition = StepPosition.First;
constructor(private componentFactoryResolver: ComponentFactoryResolver, private viewContainerRef: ViewContainerRef) { }
public ngOnInit() {
}
public onSelectStep(contentItem: WizContentItem) {
console.log("step was clicked");
console.log(contentItem);
if (this.currentContentItem !== undefined &&
!this.validateStep(this.currentContentItem)) {
return;
}
if (this.currentWizContentComponent !== undefined ) {
this.currentContentItem.stepProgressStatus = this.currentWizContentComponent.stepProgressStatus;
}
contentItem.stepState = StepState.Active;
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(contentItem.component);
this.viewContainerRef.clear();
this.componentRef = this.viewContainerRef.createComponent(componentFactory);
(<WizContentComponent>this.componentRef.instance).data = contentItem.data;
(<WizContentComponent>this.componentRef.instance).stepState = contentItem.stepState;
this.currentWizContentComponent = (<WizContentComponent>this.componentRef.instance);
if (this.currentContentItem != null) {
this.currentContentItem.stepState = StepState.Empty;
}
this.currentContentItem = contentItem;
this.currentContentItem.stepState = StepState.Active;
// Get currentContentItemNumber based currentContentItem
this.currentContentItemNumber = this.wizContentItems.findIndex(wizContentItem => wizContentItem === this.currentContentItem);
this.stepChanged();
}
public onNextClick(event: Event) {
if ((this.currentContentItemNumber + 1) < this.wizContentItems.length) {
let nextContentItem = this.wizContentItems[this.currentContentItemNumber + 1];
if (nextContentItem.stepState === StepState.Disabled) {
nextContentItem = this.getNextActiveItem(this.currentContentItemNumber + 1);
}
if (nextContentItem != null) {
this.onSelectStep(nextContentItem);
}
}
}
public onPreviousClick(event: Event) {
if ((this.currentContentItemNumber - 1) >= 0) {
let previousContentItem = this.wizContentItems[this.currentContentItemNumber - 1];
if (previousContentItem.stepState === StepState.Disabled) {
previousContentItem = this.getPreviousActiveItem(this.currentContentItemNumber - 1);
}
if (previousContentItem !== null) {
this.onSelectStep(previousContentItem);
}
}
}
public getCurrentStepPosition(): StepPosition {
return this._position;
}
private validateStep(contentItem: WizContentItem): boolean {
return (<WizContentImplComponent>this.componentRef.instance).isValid();
}
private stepChanged(): void {
this._position = undefined;
if (this.currentContentItemNumber <= 0) {
this._position = StepPosition.First;
} else if (this.currentContentItemNumber >= this.wizContentItems.length) {
this._position = StepPosition.Last;
} else {
this._position = StepPosition.Middle;
}
if ((<WizContentComponent>this.componentRef.instance).isSummary) {
this._position = StepPosition.Summary;
}
this.onStepChanged.emit(this._position);
}
private getNextActiveItem(itemNumber: number): WizContentItem {
if (this.wizContentItems.length <= (itemNumber + 1)) {
return null;
}
let nextContentItem = null;
for (let i = (itemNumber); i < this.wizContentItems.length; i++) {
if ( this.wizContentItems[i].stepState !== StepState.Disabled ) {
nextContentItem = this.wizContentItems[i];
break;
}
}
return nextContentItem;
}
private getPreviousActiveItem(itemNumber: number): WizContentItem {
if ((itemNumber - 1) < 0 ) {
return null;
}
let previousContentItem = null;
for (let i = (itemNumber - 1); i >= 0; i--) {
if ( this.wizContentItems[i].stepState !== StepState.Disabled ) {
previousContentItem = this.wizContentItems[i];
break;
}
}
return previousContentItem;
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!!
作为对先前答案的补充,为了更好地比较这两种方法,可能值得添加一些有关每种情况下发生的情况的详细信息。
使用FactoryResolver服务“创建”组件的步骤:
resolveComponentFactory()
方法实例化一个组件类:该方法将组件类型作为参数,并查找相应的“组件工厂”。createComponent()
方法将新组件“附加”到视图ViewContainerRef有关信息:https : //angular.io/guide/dynamic-component-loader#resolving-components
结构指令( ngIf, ngSwitch...) “创建”组件时应用的步骤:
ViewContainerRef类(
createEmbeddedView()方法)。=> 这两种方法大致经过相同的步骤(实际上“结构指令”方法添加了一个额外的步骤,即创建嵌入式视图,我认为可以忽略不计)。
因此,在我看来,从两个选项中选择一个最有价值的原因是用例,我将其总结如下:
结构指令( ngIf, ngSwitch...):
FactoryResolver 服务:
是的,最好使用,ComponentFactoryResolver这就是为什么它在官方文档中。自Angular 2起它就位于内部,它是稳定的。对性能没有重大影响。
许多Angular库在内部也使用它,而Angular Material库也是如此。检查Component Development Kit(CDK)内的Portal及其在GitHub中的源代码,您可以在其中看到它用于在其中显示动态内容。
关于您的问题,NgSwitch使用或做组件是更好还是ComponetFactoryResolver很难回答,因为这取决于您要执行的操作,而您并未解释具体情况。我要说的是,在大多数情况下,您应该使用,ComponentFactoryResolver因为它允许您动态添加任何组件,并且没有一个大组件,NgSwitch而所有可能的动态组件都很大。仅在动态组件数量很少并且不希望添加新组件的情况下,使用创建它们可能更容易NgSwitch。
| 归档时间: |
|
| 查看次数: |
557 次 |
| 最近记录: |