gpt4 book ai didi

javascript - 使用 Angular 的 $compile 和新范围时的内存泄漏

转载 作者:IT王子 更新时间:2023-10-28 23:36:13 25 4
gpt4 key购买 nike

我想使用 javascript 动态创建 Angular 组件,然后使用 $compile 和新创建的范围对它们进行 Angular 编译。然后当我不再使用该组件时,我想销毁该组件和新范围。

一切都按预期工作,除了即使我正在销毁新范围,它使用的所有内存都不会释放。

这是该代码的简化版本的一部分:

app.controller("mainCtrl", ["$scope", "$compile", function($scope, $compile) {
var childScope;

//call this every time the button is clicked
this.createDirective = function() {
//dynamically create a new instance of the custom directive
var customDirective = document.createElement("custom-directive");

//if another child scope exists, destroy it
if (childScope) {
childScope.$destroy();
childScope = undefined;
}

//create a new child scope
childScope = $scope.$new();

//compile the custom directive
$compile(customDirective)(childScope);
};

}]);

此代码的完整工作示例是 here

所有这些代码所做的,就是在每次单击按钮时创建一个新组件,但首先销毁任何已经存在的组件。请注意,我实际上并没有在页面中添加已编译的组件,因为我注意到无论我是否使用它,泄漏仍然存在。

使用 Chrome 的开发工具(Profiles -> Record Allocation Timeline -> Start)点击按钮后我看到以下内存使用情况几次:

Memory consumption

很明显,customDirective 占用的任何内存都不会真正释放,即使正在调用作用域的 $destroy 函数。

我过去曾成功使用过 $compile 而没有创建新的范围,但在这种情况下我似乎遗漏了一些东西。我是否还应该做其他事情来确保没有对新范围的引用?

编辑

根据 JoelCDoyle 下面的回答,这里是修复方法(我在我创建的作用域中添加了一个 on destroy 函数):

app.controller("mainCtrl", ["$scope", "$compile", function($scope, $compile) {
var childScope;

//call this every time the button is clicked
this.createDirective = function() {
//dynamically create a new instance of the custom directive
var customDirective = document.createElement("custom-directive");

//if another child scope exists, destroy it
if (childScope) {
childScope.$destroy();
childScope = undefined;
}

//create a new child scope
childScope = $scope.$new();

//compile the custom directive
var compiledElement = $compile(customDirective)(childScope);

//FIX: remove the angular element
childScope.$on("$destroy", function() {
compiledElement.remove();
});
};
}]);

Fixed fiddle

最佳答案

我想我已经找到了解决方案:https://jsfiddle.net/yqw1dk0w/8/

app.directive('customDirective', function(){
return {
template: '<div ng-controller="customDirectiveCtrl"></div>',
link: function(scope, element) {
scope.$on('$destroy', function() {
element.remove();
});
}
};
});

我仍然对它的工作原理有点模糊,但是 Angular 编译文档中的指令如何编译这部分提供了一个线索:https://docs.angularjs.org/guide/compiler

$compile links the template with the scope by calling the combined linking function from the previous step. This in turn will call the linking function of the individual directives, registering listeners on the elements and setting up $watchs with the scope as each directive is configured to do.\

The result of this is a live binding between the scope and the DOM. So at this > point, a change in a model on the compiled scope will be reflected in the DOM.

我猜,销毁范围不会删除这些元素监听器。这就是上面的代码所做的:destroy directive/child scope on scope destroy

关于javascript - 使用 Angular 的 $compile 和新范围时的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39861690/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com