当手动编译在角指令内存泄漏 [英] Memory leak when manually compiling directives in Angular

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

问题描述

我想手动编译指令,并把它添加到通过jQuery的DOM。该指令是一个简单的DIV与ngClick处理程序。没有JQuery的插件是在指令本身(这似乎是许多其他的存储器泄漏线程的重点)使用。

如果你运行一个分析器,你会发现它泄漏的节点。有什么可以做的来解决这个问题或者是在JQuery中的一个问题/角?

小提琴这里结果
探查截图

HTML

 < D​​IV NG-应用=TestApp>
    <&按钮GT;< /按钮>
    < D​​IV ID =容器>< / DIV>
< / DIV>

的JavaScript

  VAR ButtonsCtrl =功能($范围,$编译){
    this.scope = $范围;
    this.compile = $编译;
};ButtonsCtrl.prototype.toggle =功能(){
    变种C = angular.element('#集装箱')儿童()。    如果(0在C&放大器;和C [0]){
        c.scope()$ destroy()方法。
        c.remove();
    }其他{
        。变种S = this.scope $新();
        this.compile('<东西颜色=蓝>< /&东西GT;')(S).appendTo('#集装箱');
    }
};VAR ThingCtrl =功能($范围内){};
ThingCtrl.prototype.clicky =功能(){
    警报('测试');
};变种模块= angular.module('组件',[]);
module.directive('按钮',函数(){
    返回{
        限制:'E',
        模板:'<按钮NG点击=ctrl.toggle()>拨动< /按钮>,
        控制器:ButtonsCtrl,
        controllerAs:CTRL
    }
});module.directive('东西',函数(){
    返回{
        限制:'E',
        范围: {
            颜色:'@'
        },
        模板:'< D​​IV的风格=宽度:50像素,高度:50像素;背景:{{颜色}}; NG-点击=ctrl.clicky()>< / DIV>,
        控制器:ThingCtrl,
        controllerAs:CTRL
    };
});angular.module('TestApp',['分量']);


解决方案

如果您缓存模板函数$编译的回报,然后调用一个新的范围,内存泄漏似乎减少到每次点击的唯一节点。

  VAR ButtonsCtrl =功能($范围,$编译){
    this.scope = $范围;
    this.makeThing = $编译('<东西颜色=蓝>< /&东西GT;');
    this.thingScope = NULL;
};

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

  ButtonsCtrl.prototype.toggle =功能(){
    VAR容器=的document.getElementById('集装箱');    如果(this.thingScope){
        container.removeChild(container.childNodes [0]);
        this.thingScope $ destroy()方法。
        this.thingScope = NULL;
    }其他{
        this.thingScope = this.scope美元的新()。
        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.

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

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