当组件被销毁时,Angular 如何销毁事件处理程序和属性绑定

Posted

技术标签:

【中文标题】当组件被销毁时,Angular 如何销毁事件处理程序和属性绑定【英文标题】:How does Angular destroy event handlers and property bindings when a component is destroyed 【发布时间】:2018-03-23 03:58:27 【问题描述】:

我试图比我在文档中找到的更详细地了解 Angular 组件的销毁过程。我希望这里有人能够回答以下问题:

组件模板中元素的属性是否在移除此类元素的事件侦听器之前被移除?

在组件的销毁过程中,事件监听器的注销是什么时候,如何发生的?

是否有更多关于在 Angular 内部删除事件监听器的过程的信息?

【问题讨论】:

【参考方案1】:

javascript 中,您不能删除 DOM 节点本身。如果你有以下 DOM 树:

div.children
   span

要“销毁”一个跨度,您只需将其从div.children 中删除即可。如果没有更多指向span 元素的链接,它将被垃圾回收。对象也是如此。

想象一下 Angular 中的以下结构:

ComponentA.nodes
   ComponentBElement -> ComponentBClass

现在 Angular 需要“销毁”ComponentB。为此,它只需将ComponentBElement 与父ComponentA.nodes 分离。这就是 Angular 所做的,例如,当你执行 viewContainerRef.clear():

function execRenderNodeAction(...) 
  const renderer = view.renderer;
  switch (action) 
    ...
    case RenderNodeAction.RemoveChild:
      renderer.removeChild(parentNode, renderNode);
      break; 

现在,假设 Angular 向 ComponentBElement 或其子级添加了一些事件侦听器。

是否需要显式调用removeEventListners? Usually no,因为一旦 DOM 元素被移除,事件监听器也会被垃圾回收。但是,有可能在某些异步任务或继续存在的对象中捕获对事件侦听器的引用。这可以防止侦听器和 DOM 被垃圾收集。所以 Angular 确保事件监听器被移除(在 v5 中它是 DomEventsPlugin.removeEventListener 方法)。

当 Angular 创建组件视图时,它会调用 listenToElementOutputs:

function listenToElementOutputs(view, compView, def, el) 
    for (var i = 0; i < def.outputs.length; i++) 
        ...
        var disposable = listenerView.renderer.listen(listenTarget || el, output.eventName, handleEventClosure));
        ((view.disposables))[def.outputIndex + i] = disposable; <------
    

您可以看到使用renderer 附加事件,然后将取消订阅回调(一次性)存储到view.disposables。当 Angular 销毁视图时,会执行这些一次性操作并删除事件侦听器。:

function [destroyView](view) 
    ...
    if (view.disposables) 
        for (var i = 0; i < view.disposables.length; i++) 
            view.disposables[i](); <----------------
        
    

要了解有关视图和编译的更多信息,请阅读:

Here is what you need to know about dynamic components in Angular Here is why you will not find components inside Angular

【讨论】:

感谢您为我澄清了一点!您是否也碰巧知道,在此过程中的某个时间点,绑定到视图的属性是否被删除? Angular 是否以与视图中的事件侦听器相同的方式跟踪这些? 不客气,属性绑定到视图 - 你是什么意思?你能举个例子吗? 抱歉,有点不清楚。例如。 &lt;table [border]="border" [attr.height]="height" [width]="width"&gt;。这里的 borderheightwidth 类变量绑定到 table 的相应属性(和属性)元素。我想知道的是,当组件被销毁时,Angular 是否会对这些绑定做任何事情,以及我可以在哪里找到有关 Angular 如何删除它们的更多信息(如果确实如此)。谢谢! @MrMalt,这些绑定的附加方式不需要任何删除。阅读The mechanics of DOM updates in Angular,了解更多关于绑定是如何处理的

以上是关于当组件被销毁时,Angular 如何销毁事件处理程序和属性绑定的主要内容,如果未能解决你的问题,请参考以下文章

Angular2子组件在ngFor中意外销毁

怎么监听小程序被销毁

Angular 组件在被销毁后仍在监听订阅 [重复]

一篇文章带你搞懂JS对象的自我销毁

在Android中销毁布局时覆盖的方法

Angular 控制器生命周期和事件处理