假设我有一个带有一个大数组的ng-repeat。
当ng-repeat运行时,它将该数组的每个元素添加到一个独立的作用域中,并将该数组本身添加到一个作用域中。这意味着$digest会检查整个数组的更改,最重要的是,它会检查该数组中的每个元素是否有更改。
将this plunker作为我正在讨论的一个示例。
在我的用例中,我从不更改数组的任何一个元素,所以我不需要监视它们。我将只更改整个数组,在这种情况下,ng-repeat将重新呈现整个表。(如果我说错了,请告诉我。)
在(比方说) 1000行的数组中,我不需要计算的表达式又多了1000个。
如何在仍在监视主数组的同时从观察器中注销每个元素?
也许我可以更多地控制我的$digest,并以某种方式跳过每一行,而不是取消注册?
这个特定的案例实际上是一个更普遍的问题的例子。我知道$watch returns a 'deregisteration' function,但在大多数情况下,当指令注册手表时,这并不起作用。
发布于 2012-12-01 03:53:01
有一个大阵列的中继器,你并不是为了观看每一个项目而观看的。
您需要创建一个自定义指令,该指令将一个参数和表达式传递给您的数组,然后在链接函数中,您只需查看该数组,并让链接函数以编程方式刷新HTML (而不是使用ng-repeat)。
类似于(psuedo-code):
app.directive('leanRepeat', function() {
return {
restrict: 'E',
scope: {
'data' : '='
},
link: function(scope, elem, attr) {
scope.$watch('data', function(value) {
elem.empty(); //assuming jquery here.
angular.forEach(scope.data, function(d) {
//write it however you're going to write it out here.
elem.append('<div>' + d + '</div>');
});
});
}
};
});
..。这看起来很让人头疼。
替代黑客方法
您可以遍历$scope.$$watchers
并检查$scope.$$watchers[0].exp.exp
以查看它是否与您想要删除的表达式匹配,然后通过一个简单的splice()
调用删除它。这里的要点是,像标记之间的Blah {{whatever}} Blah
这样的东西将是表达式,甚至还将包括回车。
从好的方面来说,你也许能够循环通过你的ng- $scope,删除所有的东西,然后显式地添加你想要的监视……我不知道。
不管怎样,这看起来像是一次黑客攻击。
删除由$scope.$watch制作的监视器的
您可以使用$watch
调用返回的函数注销$watch
:
例如,要使$watch
只触发一次:
var unregister = $scope.$watch('whatever', function(){
alert('once!');
unregister();
});
当然,您可以随时调用注销函数...这只是一个例子。
结论:没有一种很好的方法可以完全按照的要求去做
但有一件事需要考虑:这值得担心吗?此外,将数以千计的记录加载到几十个DOMElements中真的是一个好主意吗?发人深省。
我希望这能有所帮助。
EDIT 2(删除坏主意)
发布于 2016-02-23 02:07:50
$watch返回一个函数,该函数在被调用时解除绑定$watch。所以这就是“watchOnce”所需要的:
var unwatchValue = scope.$watch('value', function(newValue, oldValue) {
// Do your thing
unwatchValue();
});
发布于 2013-06-28 20:16:54
编辑:查看我发布的另一个答案。
我已经以一种可分离的方式实现了blesh的想法。我的ngOnce
指令只是销毁了ngRepeat
在每个项目上创建的子范围。这意味着作用域不能从其父对象的scope.$digest
访问,并且监视器永远不会被执行。
Source and example on JSFiddle
指令本身:
angular.module('transclude', [])
.directive('ngOnce', ['$timeout', function($timeout){
return {
restrict: 'EA',
priority: 500,
transclude: true,
template: '<div ng-transclude></div>',
compile: function (tElement, tAttrs, transclude) {
return function postLink(scope, iElement, iAttrs, controller) {
$timeout(scope.$destroy.bind(scope), 0);
}
}
};
}]);
使用它:
<li ng-repeat="item in contents" ng-once>
{{item.title}}: {{item.text}}
</li>
Note ng-once
不会创建自己的作用域,这意味着它会影响同级元素。它们做的都是一样的事情:
<li ng-repeat="item in contents" ng-once>
{{item.title}}: {{item.text}}
</li>
<li ng-repeat="item in contents">
<ng-once>
{{item.title}}: {{item.text}}
</ng-once>
</li>
<li ng-repeat="item in contents">
{{item.title}}: {{item.text}} <ng-once></ng-once>
</li>
https://stackoverflow.com/questions/13651578
复制相似问题