在 Angular 中手动编译指令时出现内存泄漏 [英] Memory leak when manually compiling directives in Angular

查看:23
本文介绍了在 Angular 中手动编译指令时出现内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

在这里小提琴
Profiler 截图

HTML

<按钮></按钮><div id="容器"></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();} 别的 {var s = this.scope.$new();this.compile('<thing color="blue"></thing>')(s).appendTo('#container');}};var ThingCtrl = function($scope) {};ThingCtrl.prototype.clicky = function() {警报('测试');};var module = angular.module('components', []);module.directive('buttons', function() {返回 {限制:'E',模板:'<button ng-click="ctrl.toggle()">toggle</button>',控制器:ButtonsCtrl,控制器为:'ctrl'}});module.directive('东西', function() {返回 {限制:'E',范围: {颜色: '@'},模板:'<div style="width:50px;height:50px;background:{{color}};"ng-click="ctrl.clicky()"></div>',控制器:ThingCtrl,控制器为:'ctrl'};});angular.module('TestApp', ['components']);

解决方案

如果你缓存 $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');如果(this.thingScope){container.removeChild(container.childNodes[0]);this.thingScope.$destroy();this.thingScope = null;} 别的 {this.thingScope = this.scope.$new();container.appendChild(this.makeThing(this.thingScope)[0]);}};

看看你的想法.

I'm trying to manually compile a directive and add it to the DOM via JQuery. The directive is a simple div with an ngClick handler. No JQuery plugins are used in the directive itself (which seems to be the focus of many of the other memory leak threads).

If you run a profiler you will find that it leaks nodes. Is there something that can be done to fix this or is it a problem in 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']);

解决方案

If you cache the template function that $compile returns, then call that with a new scope, the memory leak seems to decrease to only one node per click.

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

Additionally, removing the jQuery wrappers from the ButtonsCtrl.toggle() method appears to eliminate the node leak altogether.

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.

这篇关于在 Angular 中手动编译指令时出现内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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