【发布时间】:2018-03-23 03:58:27
【问题描述】:
我试图比我在文档中找到的更详细地了解 Angular 组件的销毁过程。我希望这里有人能够回答以下问题:
组件模板中元素的属性是否在移除此类元素的事件侦听器之前被移除?
在组件的销毁过程中,事件监听器的注销是什么时候,如何发生的?
是否有更多关于在 Angular 内部删除事件监听器的过程的信息?
【问题讨论】:
标签: angular angular-components
我试图比我在文档中找到的更详细地了解 Angular 组件的销毁过程。我希望这里有人能够回答以下问题:
组件模板中元素的属性是否在移除此类元素的事件侦听器之前被移除?
在组件的销毁过程中,事件监听器的注销是什么时候,如何发生的?
是否有更多关于在 Angular 内部删除事件监听器的过程的信息?
【问题讨论】:
标签: angular angular-components
在 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](); <----------------
}
}
要了解有关视图和编译的更多信息,请阅读:
【讨论】:
<table [border]="border" [attr.height]="height" [width]="width">。这里的 border、height 和 width 类变量绑定到 table 的相应属性(和属性)元素。我想知道的是,当组件被销毁时,Angular 是否会对这些绑定做任何事情,以及我可以在哪里找到有关 Angular 如何删除它们的更多信息(如果确实如此)。谢谢!