使用自定义DataTables指令时,我遇到了大量的内存泄漏。该指令使用Jquery的DataTables插件,并且有一个函数会导致内存泄漏。
var rowCompiler = function(nRow, aData, iDataIndex) {
nRow = $compile(nRow)(scope);
}
如果我注释掉这种方法,那么我就不会看到泄漏。 rowCompiler方法获取第一列并用ID替换ID。这个列有两个指令,所以我需要使用$ compile让Angular知道这些指令。我已经尝试使用范围。$ on(' $ destroy',function()但节点和内存不断上升。
以下是数据表中呈现的HTML。
<tr class="ng-scope odd">
<td class=""><ng-menu-drop ng-idr-id="630" class="ng-isolate-scope">
<div class="menu-drop">
<li class="dropdown" style="list-style:none;"> <a class="dropdown-toggle"><i class="icon-cog icon-large"></i> </a>
<ul class="dropdown-menu">
<li><a href="#/idr/630/profile/view">Profile</a></li>
<li></li>
<li> <a href="#/idr/630/documents">Documents</a></li>
<li><a href="#/idr/630/communication">Communication </a> </li>
<li><a href="#/idr/630/hierarchy/">Hierarchy </a></li>
</ul>
</li>
</div>
</ng-menu-drop>
</td>
<td class=""><div tooltip-placement="left" tooltip="test" class="ng-scope">test</div></td>
.directive('ngMenuDrop', [ function(scope, elm, attrs) {
return{
restrict:"E,A",
scope: {
ngIdrId: '@'
},
link: function (scope, element, attrs) {
},
template: '<div class="menu-drop"><li class="dropdown" style="list-style:none;"><a class="dropdown-toggle"><i class="icon-cog icon-large"></i> </a> ' +
' <ul class="dropdown-menu" ><li><a href="#/idr/{{ngIdrId}}/profile/view">Profile</a><li><li><a href="#/idr/{{ngIdrId}}/documents">Documents</a></li><li><a href="#/idr/{{ngIdrId}}/communication">Communication </a></li><li><a href="#/idr/{{ngIdrId}}/hierarchy/">Hierarchy </a></li></ul></li></div>'
}
}])
答案 0 :(得分:1)
当你调用$ compile时,你需要确保你没有编译已经编译过的元素。这样做可能会导致内存泄漏,当元素被多次编译并且它们的$ watch没有被清理时。
如果您正在编译DOM树的一部分并发现您正在第二次编译它,那么很可能有更好的方法来构建模板。例如,您可以使用angular.element('...')或使用jquery创建模板,而不是依赖于指令定义中的'template'属性。此外,如果您正在重新编译已转换的内容,那么您应该找到一种方法,以便编译发生一次。
答案 1 :(得分:0)
有时节点泄漏是由javascript事件处理程序引起的。在与行元素有关的指令中,查找可能附加的jQuery或jqLite事件侦听器。当行被删除时,需要删除/取消引用这些行。你可以听一下'$ destroy&#39; DOM事件。这与Angular事件(范围。$ on)不同。
$ destroy - AngularJS拦截所有jqLite / jQuery的DOM破坏apis,并在被删除的所有DOM节点上触发此事件。这可用于在删除DOM元素之前清除任何第三方绑定。
在事件处理程序中,您可以删除对节点的引用,取消超时和间隔等。
element.on('$destroy', function () {/* cleanup */});
答案 2 :(得分:0)
我相信 pixelbits 是在正确的轨道上。我最近给出了一个答案submitted及其附带的jsfiddle,证明缓存linking function $ compile返回大大减少了节点泄漏。因此,正如 pixelbits 所说的那样,尝试$只编译模板一次,然后保存生成的链接函数,并在要绑定到编译指令的作用域上调用它。
除了先前引用的文档解释编译过程涉及克隆模板元素之外,我不能告诉你很多关于Angular在$ compile中对节点做什么的内部,但也许其他问题,答案和小提琴可以指向你朝着正确的方向前进。