gpt4 book ai didi

angular - 在 Angular7 应用程序中使用 ComponentFactoryResolver 是个好主意吗?

转载 作者:太空狗 更新时间:2023-10-29 18:05:00 29 4
gpt4 key购买 nike

我想创建一个动态加载不同组件的 Angular 7 Web 应用程序,如本官方文档中所示: https://angular.io/guide/dynamic-component-loader

但我不确定使用 ComponentFactoryResolver 是否是个好主意。我没用过,不知道稳定不,性能也不知道。

我想要一些关于它的意见,如果有人知道任何替代方案。我不想使用 native innerHTML

我正在尝试创建一个带有动态步骤的自定义和通用向导。这个向导有

  • 标题组件
  • 向导步骤
  • 一个“容器”。现在我正在使用 ng-template 显示每个步骤的内容(一个单独的组件,在某些情况下是一个复杂的组件)
  • 向导按钮(下一步和上一步)和最后一步的操作按钮,如保存等

这些步骤是动态的。基于一些业务逻辑,例如用户在前面步骤中的输入。

我当前的实现:
我将只展示我使用 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;
}
}

谢谢!!

最佳答案

是的,使用 ComponentFactoryResolver 很好,这就是它出现在官方文档中的原因。自 Angular 2 以来,它在内部是稳定的。它没有显着的性能影响。

许多 Angular 库在内部也使用它 Angular Material library .检查Portal inside the Component Development Kit (CDK)及其 source in GitHub您可以在其中看到它用于显示其中的动态内容。

关于您的问题是使用 NgSwitch 还是使用 ComponetFactoryResolver 创建组件更好,这个问题很难回答,因为这取决于您尝试做什么和您做了什么不解释你的场景到底是什么。我想说的是,在大多数情况下,您应该使用 ComponentFactoryResolver,因为它允许您动态添加任何组件,并且您没有一个包含巨大 NgSwitch 的大型组件可能的动态组件。只有在您的动态组件数量非常少并且您不希望添加新组件的情况下,使用 NgSwitch 创建它们可能更容易。

关于angular - 在 Angular7 应用程序中使用 ComponentFactoryResolver 是个好主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56430398/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com