销毁组件时,Angular如何销毁事件处理程序和属性绑定 [英] How does Angular destroy event handlers and property bindings when a component is destroyed

查看:276
本文介绍了销毁组件时,Angular如何销毁事件处理程序和属性绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to understand the destruction process of Angular Components a bit more detailed than what I could find in the documentation. I was hoping someone here would be able to answer the following questions:

在删除此类元素的事件侦听器之前,是否删除了Component模板中元素的属性?

Are properties on elements in the Component template removed before the event listeners of such elements are removed?

在组件的销毁过程中,何时以及如何注销事件监听器?

In the destruction process of a Component, when and how does the de-registration of an event listener happen?

在Angular内部是否还有其他有关删除事件侦听器的过程的可用信息?

Is there any more information available concerning the process of removing event listeners internally in Angular?

推荐答案

在JavaScript中,您本身无法删除DOM节点.如果您具有以下DOM树:

In JavaScript you cannot remove a DOM node per-se. If you have the following DOM tree:

div.children
   span

要破坏"跨度,只需要将其从div.children中删除.如果没有指向span元素的链接,则将对其进行垃圾回收.对于对象也是如此.

To "destroy" a span you simply need to remove it from the div.children. If there are no more links pointing to the span element it will be garbage collected. And the same holds true for objects.

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

Imagine the following structure in Angular:

ComponentA.nodes
   ComponentBElement -> ComponentBClass

现在,Angular需要销毁" ComponentB.为此,只需将ComponentBElement与父ComponentA.nodes分离.这就是Angular的功能,例如,当您执行viewContainerRef.clear():

Now Angular needs to "destroy" ComponentB. To do that it simply detaches ComponentBElement from the parent ComponentA.nodes. And this is what Angular does, for example, when you execute viewContainerRef.clear():

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

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

Now, suppose Angular added some event listeners to ComponentBElement or its children.

是否需要显式调用removeEventListners? 通常不会,因为一旦删除了DOM元素,事件监听器也会被垃圾回收.但是,有可能在某些异步任务或继续存在的对象中捕获了对事件侦听器的引用.这样可以防止侦听器和DOM被垃圾回收.因此Angular确保删除事件监听器(在v5中为

Is there any need to explicitly call removeEventListners? Usually no, because once DOM elements are removed the event listeners are garbage collected as well. However, there's a possibility that a reference to the event listener is captured in some async task or an object that continues to live. This prevents the listener and the DOM from being garbage collected. So Angular ensures that event listeners are removed (in v5 it's DomEventsPlugin.removeEventListener method).

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

When Angular creates a component view it calls 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销毁视图时,将执行这些一次性对象,并删除事件侦听器.

You can see that event is attached using renderer and then the unsubscription callback (disposable) is stored into view.disposables. When Angular destroys a view these disposables are executed and event listeners are removed.:

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

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

To learn more about views and compilation read:

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

这篇关于销毁组件时,Angular如何销毁事件处理程序和属性绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆