【问题标题】:Delete Dynamically Created Components, one by one?一个一个地删除动态创建的组件?
【发布时间】:2020-07-04 16:09:26
【问题描述】:

我可以动态创建多个组件,并且我希望能够通过单击每个组件上的按钮来分别删除每个组件。我有一个工作演示项目,我尽可能简单。 请看我的stackblitz。您可以通过多次单击创建按钮来创建多个组件。这就是我希望它工作的方式。但是,我希望有一个更简单的方法。 这里是 app.component.ts

import {
  Component,
  ViewChild,
  ComponentFactoryResolver,
  ViewContainerRef,
  ComponentRef,
  OnDestroy
} from "@angular/core";
import { DynamicComponent } from "./dynamic/dynamic.component";
@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnDestroy {
  private _count = 0;
  componentRef: ComponentRef<DynamicComponent>;
  dynamics: Map<string, ComponentRef<DynamicComponent>> = new Map();
  @ViewChild("viewcontainer", { read: ViewContainerRef, static: false })
  viewContainerRef: ViewContainerRef;
  constructor(private resolver: ComponentFactoryResolver) {}
  createComponent() {
    this._count++;
    const factory = this.resolver.resolveComponentFactory(DynamicComponent);
    this.componentRef = this.viewContainerRef.createComponent(factory);
    this.componentRef.instance.name = " " + this._count;
    this.dynamics.set(this.componentRef.instance.name, this.componentRef);
    this.componentRef.instance.deleteName.subscribe(
      name => this.destroyComponent(name),
      error => console.log(error)
    );
  }
  destroyComponent(name: string) {
    if (this.dynamics.has(name)) {
      this.dynamics.get(name).destroy();
    }
    this.dynamics.delete(name);
  }
  ngOnDestroy() {
    this.dynamics.forEach(
      (value: ComponentRef<DynamicComponent>, key: string) => {
        value.instance.deleteName.unsubscribe();
      }
    );
    this.dynamics = null;
  }
}

这里是 app.component.html

<button (click)="createComponent()">Create a Component</button>
<ng-container #viewcontainer></ng-container>

这里是 dynamic.component.ts

import { Component, Input, Output, EventEmitter } from "@angular/core";

@Component({
  selector: "app-dynamic",
  templateUrl: "./dynamic.component.html",
  styleUrls: ["./dynamic.component.css"]
})
export class DynamicComponent {
  @Input() name: string;
  @Output() deleteName = new EventEmitter<string>();
  constructor() {}
  delete() {
    this.deleteName.emit(this.name);
  }
}

这里是dynamic.component.html

<div>
    {{ name }} <button (click)="delete()">Delete</button>
</div>

我在 app.module.ts 中添加了以下行

entryComponents: [DynamicComponent]

我的问题:有没有更简单的方法?可以使用@ViewChildren 吗?像什么?

@ViewChildren(DynamicComponent) dynamics: QueryList<DynamicComponent>;  

编辑: 睡了一夜之后,我有了另一个想法。为什么不让每个动态组件都持有对其自身的引用。请看我的第二个stackblitz。该项目不使用地图来保存所有动态的所有 ComponentRef。我只是在每个 DynamicComponent 中保存一个 ComponentRef。但是,它会引发错误。

DynamicComponent_Host.ngfactory.js? [sm]:1 ERROR RangeError: Maximum call stack size exceeded
    at callWithDebugContext (services.ts:636)
    at Object.debugDestroyView [as destroyView] (services.ts:355)
    at ViewRef_.destroy (refs.ts:284)
    at ComponentRef_.destroy (refs.ts:122)
    at DynamicComponent.ngOnDestroy (dynamic.component.ts:20)
    at callProviderLifecycles (provider.ts:575)
    at callElementProvidersLifecycles (provider.ts:541)
    at callLifecycleHooksChildrenFirst (provider.ts:529)
    at destroyView (view.ts:511)
    at callWithDebugContext (services.ts:630)

我不明白为什么我的第二个项目不起作用。第一个(在此处的顶部)有效。 编辑:我找到了How to let a component delete itself on a button click with in angular
我想这会比使用 ComponentFactoryResolver 容易得多。 编辑:我在 How to destroy component created dynamically angular 8
找到了类似的问题和解决方案 编辑:我刚刚找到What is the proper use of an EventEmitter? 所以,猜猜我的第一个项目滥用了EventEmitter?

【问题讨论】:

    标签: angular


    【解决方案1】:

    在您的第二个项目中,您在 ngOnDestroy 生命周期回调中调用 this.selfref.destroy()。这会创建一个无限循环,因为ngOnDestroy 是由对this.selfref.destroy() 的调用触发的。您不需要像那样显式处理ComponentRef。毕竟是参考。

    如果您删除对this.selfref.destroy() 的调用,您的第二个项目就会发挥作用。

    【讨论】:

    • 我是对的。当我在 DynamicComponent 的 ngOnDestroy 方法中删除该行时,错误消失了。我仍然想知道 ComponentFactory。我觉得这一切都变得太贵了。也许,他们在stackoverflow.com/questions/54112649/… 生成组件的方式是一个不错的选择?
    猜你喜欢
    • 2019-03-24
    • 2018-01-21
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 2020-12-07
    • 1970-01-01
    • 2022-08-06
    • 1970-01-01
    相关资源
    最近更新 更多