在Angular.JS项目中,我有一个指令与一个复杂的模板,实例化数千次(在网格中)。Angular JS范围泄漏与element.empty()
由于性能原因,我不得不在多个子模板中拆分模板。根据指令的范围值组合,我选择一个子模板。
性能增益是真实的(在非常大的网格上大于100),但在某些情况下(当子模板包含ng-repeat指令时)Angular正在调用在删除的DOM元素范围内声明的函数。
我的问题归纳为以下最小代码:
angular.module('myApp', []).directive('myDirective', ['$compile', '$log', function ($compile, $log) {
function display(scopeId, x) {
$log.log('func called with', x, 'in scope', scopeId);
return x;
}
return {
scope: true,
link: function (scope, element) {
scope.array = [1, 2, 3];
scope.display = display;
scope.$watch(function() {
return scope.abc;
}, function (newValue) {
var newContent = angular.element('<div ng-repeat="item in array">{{display($id, item)}}</div>');
element.empty();
element.append($compile(newContent)(scope))
});
}
};
}]);
你可以在这里进行测试:https://jsfiddle.net/yss4yskm/6/
每次元素被替换(当你点击复选框),通过创建的每个范围ng-repeat被泄露:作用域继续登录到浏览器控制台,Batarang也显示泄漏的作用域。
不应该element.empty()
删除所有的子范围?
为什么问题只发生在ng-repeat指令中?
我可以通过创建子范围并在需要时销毁(https://jsfiddle.net/yss4yskm/9/)来避免泄漏,但我不应该这样做。
angular.module('myApp', []).directive('myDirective', ['$compile', '$log', function ($compile, $log) {
var childScope;
function display(scopeId, x) {
$log.log('func called with', x, 'in scope', scopeId);
return x;
}
return {
scope: true,
link: function (scope, element) {
scope.array = [1, 2, 3];
scope.display = display;
scope.$watch(function() {
return scope.abc;
}, function (newValue) {
element.empty();
if (childScope) {
childScope.$destroy();
}
element.append(angular.element('<div ng-repeat="item in array">{{display($id, item)}}</div>'));
childScope = scope.$new();
$compile(element.contents())(childScope);
});
}
};
}]);
谢谢。
你应该做'element.remove()'它也会删除范围.. –
'element.remove()'不会删除范围。范围需要被明确销毁。 –