How does Angular destroy event handlers and property bindings when a component is destroyed

纵然是瞬间 提交于 2019-12-08 05:01:13

问题


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:

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?

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


回答1:


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

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.

Imagine the following structure in Angular:

ComponentA.nodes
   ComponentBElement -> ComponentBClass

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; 

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

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).

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; <------
    }
}

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


来源:https://stackoverflow.com/questions/46688843/how-does-angular-destroy-event-handlers-and-property-bindings-when-a-component-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!