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创建组件。
解决方案
推荐方案:改用官方标准动态加载方式
- 先创建组件选择器→组件类的映射表,把所有需要动态加载的组件都加进去:
// 在你的组件文件顶部,导入所有需要动态加载的组件 import { ExampleComponent } from './example/example.component'; import { DemoComponent } from './demo/demo.component'; // 建立selector和组件类的对应关系 const ComponentSelectorMap = { 'app-example': ExampleComponent, 'app-demo': DemoComponent // 继续添加其他需要动态加载的组件 };
- 修改
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
相关产品推荐
相关产品推荐

