销毁使用Renderer2创建的元素的正确方法是什么?

ins*_*hex 7 angular

在我们的代码库中,我们有一个虚拟重复指令,它使用Renderer2来创建一个这样的div:

this.renderer2.createElement('div');
Run Code Online (Sandbox Code Playgroud)

在ngOnDestroy方法中,我们像这样销毁它:

this.renderer.destroyNode(this.offsetBeforeEl);
Run Code Online (Sandbox Code Playgroud)

这工作正常,我们没有问题,直到我们在prod模式下构建应用程序,我们开始收到以下错误:

main.js?d73b003…:formatted:87193 Uncaught (in promise) TypeError: this.renderer.destroyNode is not a function
Run Code Online (Sandbox Code Playgroud)

我在该行添加了一个断点,发现实际上destroyNode不是Renderer2上的方法.我去了angular的源代码,并在抽象类定义中找到了方法上方的注释:

/**
   * This property is allowed to be null / undefined,
   * in which case the view engine won't call it.
   * This is used as a performance optimization for production mode.
   */
  destroyNode: ((node: any) => void)|null; 
Run Code Online (Sandbox Code Playgroud)

所以我检查了视图的代码并看到了这个:

if (view.renderer.destroyNode) {
  destroyViewNodes(view);
}
if (isComponentView(view)) {
  view.renderer.destroy();
}
Run Code Online (Sandbox Code Playgroud)

如果我不能依赖现有的方法,那么破坏使用Renderer2动态创建的节点的正确方法是什么?

Max*_*kyi 6

使用renderer.removeChild方法。

直到我们以生产模式构建应用程序

destroyNode方法在DebugRenderer2上定义,在生产模式下不使用。

可以从angular的处理方式中推断出处理节点删除的正确方法,例如,以下execRenderNodeAction函数:

function execRenderNodeAction(
    view: ViewData, renderNode: any, action: RenderNodeAction, parentNode: any, nextSibling: any,
    target?: any[]) {
  const renderer = view.renderer;
  switch (action) {
    case RenderNodeAction.RemoveChild:
      renderer.removeChild(parentNode, renderNode);
      break;
Run Code Online (Sandbox Code Playgroud)

因此,使用removeChild像这样:

    const parent = this.renderer.createElement('div');
    const child = this.renderer.createElement('span');
    this.renderer.appendChild(parent, child);

    // using remove child
    this.renderer.removeChild(parent, child);
Run Code Online (Sandbox Code Playgroud)


Sim*_*ver 5

要删除所有子项,您必须遍历子项元素。请注意,这children不是真正的数组,因此必须先进行转换。

        Array.from(this.elementRef.nativeElement.children).forEach(child => {
            console.log('children.length=' + this.elementRef.nativeElement.children.length);
            this.renderer.removeChild(this.elementRef.nativeElement, child);
       }); 
Run Code Online (Sandbox Code Playgroud)

日志记录语句表明,实际上并没有实时地从DOM中实时删除子级-这就是为什么while循环无法删除的原因lastChild

如果这些元素不是您最初添加的,请格外小心-因为如果它们是组件,则可能会导致内存泄漏或各种怪异现象。上面仅测试了将自己添加到空元素节点中的元素。

我认为我应该可以[...this.elementRef.nativeElement.children],但是抱怨slice并不存在-所以我回复到Array.from