Angular中TypeScript动态加载组件渲染为[object Object]问题咨询
问题原因
- 直接通过
new CloneComponentComponent()创建的只是组件类的普通实例,没有经过Angular框架的编译、依赖注入、模板渲染流程,没有生成对应的DOM元素,调用toString()方法只会输出默认的[object Object]字符串,自然无法正常显示组件内容。 - 直接调用原生DOM API
document.getElementById操作DOM不符合Angular的声明式开发规范,也容易绕过Angular的变更检测机制引发后续问题。 - 额外问题:你在
app.component.html中写了完整的<html>、<head>、<body>标签是错误的,Angular的组件模板只会插入到index.html中<app-root>节点内部,重复写根标签会生成非法嵌套的DOM结构,需要删除这些外层标签,只保留业务内容部分。
推荐解决方案(最符合Angular最佳实践)
不需要用到动态创建组件的复杂API,用*ngFor声明式循环渲染即可:
- 改造
app.component.ts,用数组存储用户项的标识,点击按钮时往数组追加元素即可:
import { Component } from '@angular/core'; import { CloneComponentComponent } from './clone-component/clone-component.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'UserManager'; // 存储用户项标识,初始1个对应默认的录入项,也可以初始为空 userItems: number[] = [0]; // 自增ID用于区分不同用户项 autoId = 1; cloneUpper(){ console.log("Cloned!"); this.userItems.push(this.autoId++); } }
- 改造
app.component.html,用*ngFor循环渲染你的CloneComponentComponent组件(假设你的组件selector是app-clone-component,如果不是替换成你自己定义的selector即可):
<h1>Test Umgebung</h1> <div> <label>Firstname</label> <input placeholder="Firstname"/> </div> <div> <label>Lastname</label> <input placeholder="Lastname"/> </div> <div id="cloneContainer"> <!-- 循环渲染用户录入组件 --> <app-clone-component *ngFor="let id of userItems"></app-clone-component> </div> <button (click)="cloneUpper()">+ Add more Users</button>
如果需要获取所有用户的录入数据,可以给CloneComponentComponent加双向绑定,或者用服务存储所有用户的数据即可。
动态创建组件的可选实现
如果你的场景必须要手动动态创建组件,可以用Angular提供的ViewContainerRefAPI实现:
- 给cloneContainer节点加模板引用标记:
<div #cloneContainer></div>
- 在ts中获取
ViewContainerRef实例,调用createComponent方法创建组件:
import { Component, ViewChild, ViewContainerRef } from '@angular/core'; import { CloneComponentComponent } from './clone-component/clone-component.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'UserManager'; @ViewChild('cloneContainer', {read: ViewContainerRef}) cloneContainer!: ViewContainerRef; cloneUpper(){ console.log("Cloned!"); // 直接通过ViewContainerRef创建并渲染组件 this.cloneContainer.createComponent(CloneComponentComponent); } }
注意Angular 13+不需要再使用ComponentFactoryResolver,直接调用createComponent即可,更低版本需要先解析组件工厂再创建。
内容的提问来源于stack exchange,提问作者Florian Haberfellner
相关产品推荐
相关产品推荐

