【问题标题】:Memory leak when manually compiling directives in Angular在 Angular 中手动编译指令时发生内存泄漏
【发布时间】:2014-06-24 16:54:06
【问题描述】:

我正在尝试手动编译指令并通过 JQuery 将其添加到 DOM。该指令是一个带有 ngClick 处理程序的简单 div。指令本身没有使用 JQuery 插件(这似乎是许多其他内存泄漏线程的焦点)。

如果您运行分析器,您会发现它会泄漏节点。有什么办法可以解决这个问题,还是 JQuery/Angular 中的问题?

Fiddle here
Profiler screenshot

HTML

<div ng-app="TestApp">
    <buttons></buttons>
    <div id="container"></div>
</div>

Javascript

var ButtonsCtrl = function($scope, $compile) {
    this.scope = $scope;
    this.compile = $compile;
};

ButtonsCtrl.prototype.toggle = function() {
    var c = angular.element('#container').children();

    if (0 in c && c[0]) {
        c.scope().$destroy();
        c.remove();
    } else {
        var s = this.scope.$new();
        this.compile('<thing color="blue"></thing>')(s).appendTo('#container');
    }
};

var ThingCtrl = function($scope) {};
ThingCtrl.prototype.clicky = function() {
    alert('test');
};

var module = angular.module('components', []);
module.directive('buttons', function() {
    return {
        restrict: 'E',
        template: '<button ng-click="ctrl.toggle()">toggle</button>',
        controller: ButtonsCtrl,
        controllerAs: 'ctrl'
    }
});

module.directive('thing', function() {
    return {
        restrict: 'E',
        scope: {
            color: '@'
        },
        template: '<div style="width:50px;height:50px;background:{{color}};" ng-click="ctrl.clicky()"></div>',
        controller: ThingCtrl,
        controllerAs: 'ctrl'
    };
});

angular.module('TestApp', ['components']);

【问题讨论】:

  • 错误/泄漏究竟是什么?请编辑问题并将这些详细信息放入。:-)
  • 我已经提到它会泄漏节点。我更新了最初不正确的小提琴链接。 Click here for profiler screenshot

标签: jquery angularjs memory-leaks angularjs-directive


【解决方案1】:

如果你缓存 $compile 返回的模板函数,然后用新的作用域调用它,内存泄漏似乎减少到每次点击只有一个节点。

var ButtonsCtrl = function($scope, $compile) {
    this.scope = $scope;
    this.makeThing = $compile('<thing color="blue"></thing>');
    this.thingScope = null;
};

此外,从 ButtonsCtrl.toggle() 方法中删除 jQuery 包装似乎可以完全消除节点泄漏。

ButtonsCtrl.prototype.toggle = function() {
    var container = document.getElementById('container');

    if (this.thingScope) {
        container.removeChild(container.childNodes[0]);
        this.thingScope.$destroy();
        this.thingScope = null;
    } else {
        this.thingScope = this.scope.$new();
        container.appendChild(this.makeThing(this.thingScope)[0]);
    }
};

See what you think.

【讨论】:

  • 最好在从 DOM 中删除子作用域之前将其销毁
猜你喜欢
  • 2015-02-12
  • 2014-07-18
  • 2018-04-09
  • 2021-08-16
  • 2015-12-11
  • 2011-06-24
  • 2014-12-11
  • 2013-07-09
  • 2018-10-02
相关资源
最近更新 更多