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

Angular 8升级至12后动态加载组件报错:Cannot read properties of undefined (reading 'values')

Angular 8→12升级后动态加载组件报错:Cannot read properties of undefined (reading 'values')

错误原因

你代码里直接访问了ComponentFactoryResolver的私有属性_factories,这是Angular内部未公开的API。Angular 12对内部实现做了调整,移除了这个私有属性,导致读取values()时触发undefined错误。另外从Angular 9开始,官方就不再推荐手动获取ComponentFactory,而是直接通过ViewContainerRef.createComponent创建组件。

解决方案

推荐方案:改用官方标准动态加载方式

  1. 先创建组件选择器→组件类的映射表,把所有需要动态加载的组件都加进去:
// 在你的组件文件顶部,导入所有需要动态加载的组件
import { ExampleComponent } from './example/example.component';
import { DemoComponent } from './demo/demo.component';

// 建立selector和组件类的对应关系
const ComponentSelectorMap = {
  'app-example': ExampleComponent,
  'app-demo': DemoComponent
  // 继续添加其他需要动态加载的组件
};
  1. 修改loadComponent方法,直接通过映射表获取组件类,然后创建实例:
loadComponent(exerciseRef) {
  try {
    if (this.currentExerciseRef) {
      this.currentExerciseRef.destroy();
    }
    // 通过selector拿到对应的组件类
    const TargetComponent = ComponentSelectorMap[exerciseRef];
    if (TargetComponent) {
      const viewContainerRef = this.templatedirectiveHost.viewContainerRef;
      // Ivy编译器下直接传入组件类即可创建实例,无需手动处理factory
      const componentRef = viewContainerRef.createComponent(TargetComponent);
      this.currentExerciseRef = componentRef;
    }
  } catch (e) {
    console.log("loadComponent", e);
  }
}

注意事项

  • Angular 9+启用Ivy编译器后,不需要再配置entryComponents,只要组件在模块里声明过(declarations数组),就能被动态加载。
  • 确保路由配置里data.initselector的值和ComponentSelectorMap里的键完全匹配(区分大小写)。

为什么不推荐继续用_factories?

私有API没有官方兼容性承诺,Angular后续版本随时可能修改或移除,会导致升级时再次出现类似问题。官方推荐的方式更稳定,代码也更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 13:36:31