Javascript 递归创建动态组件
我正在尝试基于配置构建一个动态组件。组件将递归地读取配置并创建组件。发现方法ngAfterViewInit()只会被调用两次Javascript 递归创建动态组件,javascript,angular,typescript,Javascript,Angular,Typescript,我正在尝试基于配置构建一个动态组件。组件将递归地读取配置并创建组件。发现方法ngAfterViewInit()只会被调用两次 @Component({ selector: "dynamic-container-component", template: ` <div #container draggable="true" (dragstart)="dragsta
@Component({
selector: "dynamic-container-component",
template: `
<div #container
draggable="true"
(dragstart)="dragstart($event)"
(drop)="drop($event)"
(dragover)="dragover($event)"
style="border: 1px solid; min-height: 30px"></div>
`
})
export default class DynamicContainerComponent {
@Input()
dynamicConfig: DynamicConfig;
@ViewChild("container", {read: ElementRef})
private elementRef: ElementRef;
private isContainer: boolean;
private componentRef: ComponentRef<any>;
private componentRefs: ComponentRef<any>[] = [];
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
private viewContainer: ViewContainerRef,
private render: Renderer2
){
console.log("running");
}
ngAfterViewInit(){
if (this.dynamicConfig){
console.log(this.dynamicConfig)
if (this.dynamicConfig.getType() == ComponentType.INPUT){
this.isContainer = false;
let componetFactory: ComponentFactory<InputComponent> =
this.componentFactoryResolver.resolveComponentFactory(InputComponent);
this.componentRef = this.viewContainer.createComponent(componetFactory);
this.render.appendChild(this.elementRef.nativeElement, this.componentRef.location.nativeElement);
}else {
this.isContainer = true;
let items: DynamicConfig[] = this.dynamicConfig.getItems();
if (items){
for (var i=0; i<items.length; i++){
let item: DynamicConfig = items[i];
let componetFactory: ComponentFactory<DynamicContainerComponent> =
this.componentFactoryResolver.resolveComponentFactory(DynamicContainerComponent);
let componentRef: ComponentRef<DynamicContainerComponent> =
this.viewContainer.createComponent(componetFactory);
componentRef.instance.dynamicConfig = item;
this.componentRefs.push(componentRef);
this.render.appendChild(this.elementRef.nativeElement, componentRef.location.nativeElement);
}
}
}
}else {
console.log("config does not exist");
}
}
dragstart(event){
debugger;
}
drop(event){
debugger;
}
dragover(event){
debugger;
event.preventDefault();
}
}
更新
我在github中发现了类似的问题:
我做了一些别人建议的事情。但我认为这只是一个肮脏的补丁
ngAfterViewInit(){
setTimeout(function(){
if (this.dynamicConfig){
console.log(this.dynamicConfig)
if (this.dynamicConfig.getType() == ComponentType.INPUT){
this.isContainer = false;
let componetFactory: ComponentFactory<InputComponent> =
this.componentFactoryResolver.resolveComponentFactory(InputComponent);
this.componentRef = this.viewContainer.createComponent(componetFactory);
this.render.appendChild(this.elementRef.nativeElement, this.componentRef.location.nativeElement);
}else {
this.isContainer = true;
let items: DynamicConfig[] = this.dynamicConfig.getItems();
if (items){
for (var i=0; i<items.length; i++){
let item: DynamicConfig = items[i];
let componetFactory: ComponentFactory<DynamicContainerComponent> =
this.componentFactoryResolver.resolveComponentFactory(DynamicContainerComponent);
let componentRef: ComponentRef<DynamicContainerComponent> =
this.viewContainer.createComponent(componetFactory);
componentRef.instance.dynamicConfig = item;
this.componentRefs.push(componentRef);
this.render.appendChild(this.elementRef.nativeElement, componentRef.location.nativeElement);
}
}
}
}else {
console.log("config does not exist");
}
}.bind(this))
}
ngAfterViewInit(){
setTimeout(函数(){
if(this.dynamicConfig){
console.log(this.dynamicConfig)
if(this.dynamicConfig.getType()==ComponentType.INPUT){
this.isContainer=false;
让ComponentFactory:ComponentFactory=
此.componentFactoryResolver.resolveComponentFactory(InputComponent);
this.componentRef=this.viewContainer.createComponent(ComponentFactory);
this.render.appendChild(this.elementRef.nativeElement,this.componentRef.location.nativeElement);
}否则{
this.isContainer=true;
let items:DynamicConfig[]=this.DynamicConfig.getItems();
若有(项目){
对于(var i=0;i,当您创建动态组件时,angular几乎完成了更改检测周期
通过这种方式,您可以运行:
componentRef.changeDetectorRef.detectChanges()
注意:setTimeout
具有类似的效果,但会在整个应用程序上触发更改检测周期
或者将生命周期挂钩重命名为ngOnInit
此外,您向动态组件传递了错误的输入:
let item: DynamicConfig = items[i];
^^^^^^^^^^^^^
but it is not DynamicConfig instance but rather plain object
...
componentRef.instance.dynamicConfig = item;
应该是:
let item: any = items[i];
const config = new DynamicConfig();
config.assign(item);
componentRef.instance.dynamicConfig = config;
谢谢@yurzui。如果我改为ngOnInit,它会工作。我想问为什么ngOnInit会工作而不是NgoAfterViewInit。当你渲染动态组件时,它会成为更改检测树的一部分,所以它可以通过angular进行检查,但只能在更改检测周期内进行检查。当你在ngOnInit内部执行此操作时,angular会有时间进行检查在ngOnInit和NgaAfterViewInit之间设置k,但如果在NgaAfterViewInit内部渲染组件,则angular只能在下一个更改检测周期中检查它
let item: any = items[i];
const config = new DynamicConfig();
config.assign(item);
componentRef.instance.dynamicConfig = config;