在我的 angularJS 应用程序中,我有一个相当大的对象集合(数组)。我需要在不同的地方绑定(bind)到这个集合(例如显示属性:所包含对象的名称)- 绑定(bind)是必不可少的,因为这些名称可能会改变。
由于正常的 ngRepeat 会通过严格的相等比较来观察整个集合,我担心应用程序速度(我们正在谈论具有数千个或更多属性的对象)——我实际上只需要观察集合中的一般变化(比如长度,在翻转两个元素的情况下更改单个引用以及一些特定属性,如提到的 .name 属性)
我正在考虑使用以下方法(基本上创建集合的自定义副本并手动绑定(bind)到原始集合。
我的问题: 所描述的方法是否比观察原始集合更好(通过相等 - 正如我对 ngRepeater 所做的理解)或者是否有更好的方法(例如,在 watch 语句中定义某种比较回调以仅检查某些属性的变化, ...)
<script>
function QuickTestController($scope) {
// simulate data from a service
var serviceCollection = [], counter = 0,
generateElement = function() {
var element = { name:'name' + ++counter };
//var element = { name:'name' };
for (var j = 0 ; j < 5 ; j++) element['property' + j] = j;
return element;
};
for (var i = 0 ; i < 5 ; i++) {
serviceCollection.push( generateElement() );
}
// in the view controller we could either bind to the service collection directly (which should internally use a watchCollection and watch every single element for equality)
$scope.viewCollection = serviceCollection;
// watching equality of collection
/*
$scope.$watch('_viewCollectionObserve', function(newValue, oldValue) {
console.log('watch: ', newValue, oldValue);
}, true);
*/
// or we could create our own watchCollection / watch structure and watch only those properties we are interested in
$scope._viewCollectionObserve = serviceCollection;
var viewCollectionManual = [],
rebuildViewCollection = function() {
viewCollectionManual = [];
for (var i = 0, length = serviceCollection.length ; i < length ; i++) {
viewCollectionManual.push( {name:serviceCollection[i].name } );
}
console.log('- rebuildViewCollection - ');
$scope.viewCollection2 = viewCollectionManual;
},
watchCollectionProperties = [],
unregisterWatchCollection = function() {},
rebuildWatchCollectionProperties = function() {
watchCollectionProperties = [];
for (var i = 0, length = serviceCollection.length ; i < length ; i++) {
watchCollectionProperties.push('_viewCollectionObserve[' + i + ']'); // watch for ref changes
watchCollectionProperties.push('_viewCollectionObserve[' + i + '].name'); // watch for changes in specific properties
}
unregisterWatchCollection();
var watchString = '[' + watchCollectionProperties.join(',') + ']';
unregisterWatchCollection = $scope.$watchCollection(watchString, function(newValues, oldValues) {
console.log('watchCollection: ', newValues, oldValues);
rebuildViewCollection();
});
};
$scope.$watch('_viewCollectionObserve.length', function(newValue, oldValue) { // watch add / remove elements to / from collection
console.log('watch / length: ', newValue, oldValue);
rebuildWatchCollectionProperties();
});
// rebuildViewCollection();
rebuildWatchCollectionProperties();
// click handler ---
$scope.changName = function() { serviceCollection[0].name += '1'; };
$scope.changeSomeProperty = function() { serviceCollection[0].property0 += 1; };
$scope.removeElement = function() { serviceCollection.splice(0, 1); };
$scope.addElement = function() { serviceCollection.push( generateElement() ); };
$scope.switchElement = function() {
var temp = serviceCollection[0];
serviceCollection[0] = serviceCollection[1];
serviceCollection[1] = temp;
};
// will of course not react to this (this is desired behaviour!)
$scope.removeCollection = function() { serviceCollection = []; };
}
</script>
<div data-ng-controller="QuickTestController">
<ul>
<li data-ng-repeat="element in viewCollection">{{element.name}} {{element}}</li>
</ul>
<hr>
<ul>
<li data-ng-repeat="element in viewCollection2">{{element.name}} {{element}}</li>
</ul>
<button data-ng-click="changName()">changName</button>
<button data-ng-click="changeSomeProperty()">changeSomeProperty</button>
<button data-ng-click="removeElement()">removeElement</button>
<button data-ng-click="addElement()">addElement</button>
<button data-ng-click="switchElement()">switchElement</button>
<hr>
<button data-ng-click="removeCollection()">removeCollection (see comment)</button>
</div>
任何帮助/意见将不胜感激 - 请注意,我试图创建一个 fiddle 来演示我的方法但失败了:-(
(我知道基准测试可能是测试我的方法的可能解决方案,但我更想知道这里的 angularjs 专业人士的意见)
谢谢, 马蒂亚斯
最佳答案
我想你要找的是 bindonce ,这是一个高性能的绑定(bind)指令,让您可以在 AngularJS 中绑定(bind)一次属性或表达式,正如其名称所暗示的那样。
关于performance - Angularjs - 优化 ngrepeat 的观察者以仅观察集合的某些属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22916020/