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

Angular 13+动态增删组件问题:删除子组件时索引为-1无法删除

Angular 13+ 动态增删子组件异常问题:仅能删除最后一个子组件,后续删除hostView索引返回-1

在Angular 13+中实现动态增删子组件时遇到以下问题:父组件仅能删除最后一个创建的子组件,后续执行删除操作时,hostView的索引返回-1,无法从视图中移除目标子组件。曾尝试过旧版ComponentFactoryResolver的实现方式,但希望基于Angular新版本的API解决该问题。


相关代码

子组件

子组件视图(child.component.html)

<button (click)="remove_me()">I am a Child {{unique_key}}, click to Remove</button>

子组件类(child.component.ts)

import { Component } from '@angular/core';
import { ParentComponent } from '../parent/parent.component';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
})
export class ChildComponent {
  public unique_key: number;
  public parentRef: ParentComponent;

  constructor() {}

  remove_me() {
    console.log(this.unique_key);
    this.parentRef.remove(this.unique_key);
  }
}

父组件

父组件视图(parent.component.html)

<button type="button" (click)="AddChild()">
I am Parent, Click to create Child
</button>
<div>
<ng-template #viewContainerRef></ng-template>
</div>

父组件类(parent.component.ts)

import {
  ComponentRef,
  ViewContainerRef,
  ViewChild,
  Component,
} from '@angular/core';
import { ChildComponent } from '../child/child.component';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],
})
export class ParentComponent {
  @ViewChild('viewContainerRef', { read: ViewContainerRef })
  vcr!: ViewContainerRef;
  ref!: ComponentRef<ChildComponent>;

  child_unique_key: number = 0;
  componentsReferences = Array<ComponentRef<ChildComponent>>();

  constructor() {}

  AddChild() {
    this.ref = this.vcr.createComponent(ChildComponent);
    let childComponent = this.ref.instance;
    childComponent.unique_key = ++this.child_unique_key;
    childComponent.parentRef = this;
  }

  remove(key: number) {
    const index = this.vcr.indexOf(this.ref.hostView);
    console.log(index);
    if (index != -1) {
      this.vcr.remove(index);
    }
    // removing component from the list
    this.componentsReferences = this.componentsReferences.filter(
      (x) => x.instance.unique_key !== key
    );
  }
}

问题原因

  1. 全局变量ref覆盖问题:父组件中的ref变量为全局变量,每次调用AddChild时都会被新创建的子组件引用覆盖,导致其永远指向最后一个创建的子组件。当删除非最后一个子组件时,用这个ref的hostView去查询索引,自然无法找到目标组件,返回-1。
  2. 组件引用数组未维护:componentsReferences数组在创建子组件时没有将新的ComponentRef添加进去,导致后续的过滤操作无法正确移除对应组件引用。

解决方案

修改父组件的AddChild和remove方法,正确维护子组件引用数组,并根据目标unique_key找到对应的组件引用进行删除:

修改后的父组件类代码

import {
  ComponentRef,
  ViewContainerRef,
  ViewChild,
  Component,
} from '@angular/core';
import { ChildComponent } from '../child/child.component';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],
})
export class ParentComponent {
  @ViewChild('viewContainerRef', { read: ViewContainerRef })
  vcr!: ViewContainerRef;

  child_unique_key: number = 0;
  componentsReferences = Array<ComponentRef<ChildComponent>>();

  constructor() {}

  AddChild() {
    // 改用局部变量存储新组件引用
    const ref = this.vcr.createComponent(ChildComponent);
    let childComponent = ref.instance;
    childComponent.unique_key = ++this.child_unique_key;
    childComponent.parentRef = this;
    // 将新组件引用添加到数组中
    this.componentsReferences.push(ref);
  }

  remove(key: number) {
    // 根据unique_key找到目标组件引用
    const targetRef = this.componentsReferences.find(x => x.instance.unique_key === key);
    if (targetRef) {
      // 获取目标组件在容器中的索引并移除
      const index = this.vcr.indexOf(targetRef.hostView);
      if (index !== -1) {
        this.vcr.remove(index);
      }
      // 也可以直接调用destroy方法销毁组件(效果等同于remove)
      // targetRef.destroy();
      // 从引用数组中移除目标组件
      this.componentsReferences = this.componentsReferences.filter(x => x !== targetRef);
    }
  }
}

关键修改点

  • 移除全局ref变量,改用局部变量存储新创建的组件引用,并将其添加到componentsReferences数组中。
  • 在remove方法中,通过unique_key从数组中找到对应的ComponentRef,再基于该引用获取索引并执行删除操作。
  • 可选:直接调用targetRef.destroy()可以同时销毁组件并从视图容器中移除,无需手动调用vcr.remove(index)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:50:25