You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 14:表单组件工厂模式实现异常问题

Angular中表单工厂模式的实现问题

我想在Angular中实现工厂模式,用来创建多个具有不同属性的表单,因此打算构建一个表单工厂,根据传入的类型渲染对应的表单。

现有代码

app.component.html

<app-form-builder [type]="'phoneForm'"></app-form-builder>

form-builder.component.ts

interface FormMapping {
  [key: string]: ComponentRef<FormNameComponent | FormPhoneComponent>;
}

@Input() type: string = '';

constructor(public viewContainerRef: ViewContainerRef) {}

getFormTypes(type: string) {
  const formMapping: FormMapping = {
    nameForm: this.viewContainerRef.createComponent(FormNameComponent),
    phoneForm: this.viewContainerRef.createComponent(FormPhoneComponent),
  };

  formMapping[type];
}

ngOnInit(): void {
  this.getFormTypes(this.type);
}

表单组件的具体实现无关紧要:phoneForm是带input type="number"的表单,nameForm是带input type="text"的表单。

遇到的问题

使用多分支if判断的方式可以正常工作,只会渲染对应类型的表单:

getFormType(type: string) {
  if (type === 'nameForm') {
    this.viewContainerRef.createComponent(FormNameComponent);
  }

  if (type === 'phoneForm') {
    this.viewContainerRef.createComponent(FormPhoneComponent);
  }
}

但用对象映射的方式会同时渲染两个表单,不清楚原因。

问题原因

对象映射的写法中,构建formMapping对象时,会立即执行两个createComponent方法调用——不管你后续是否使用对应的属性,这两个组件都会被实例化并添加到视图容器中,所以会同时渲染。而if判断的写法只会根据传入的type执行对应的创建逻辑,因此只会渲染一个表单。

修正方案

把组件类本身存储在映射对象中,而不是直接调用createComponent,在确定需要的类型后再执行创建操作:

// 修改映射接口,存储组件类类型
interface FormMapping {
  [key: string]: typeof FormNameComponent | typeof FormPhoneComponent;
}

getFormTypes(type: string) {
  // 先清空容器,避免重复渲染
  this.viewContainerRef.clear();

  const formMapping: FormMapping = {
    nameForm: FormNameComponent,
    phoneForm: FormPhoneComponent,
  };

  const TargetFormComponent = formMapping[type];
  if (TargetFormComponent) {
    this.viewContainerRef.createComponent(TargetFormComponent);
  }
}

额外建议:每次创建组件前调用viewContainerRef.clear(),可以清空容器内已有的组件,防止多次切换类型时出现叠加渲染的问题。

内容的提问来源于stack exchange,提问作者jgcarrillo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 08:05:37