将视图绑定到服务中的数据的正确方法是什么? 我已经看到$ watch不鼓励。
我有一个视图,它从一个来自服务的数组中呈现项目。
该服务将定期从服务器刷新其数据
$http({...some params...})
.success(function(data) {
cache[key] = data;
});
在视图控制器中公开数据:
this.items = SomeFactory.cache[key]
视图具有约束力:
ng-repeat="item in $ctrl.items"
我的理解是,由于cache[key]
被分配给一个新数组,因此视图仍然绑定到旧地址,因此不会更新。
正确这样做的方法是什么?
如果我使用函数绑定它(例如:ng-repeat="item in $ctrl.items()"
但是我如何修改项目?还有性能明智我不知道这是否比直接绑定效率低?)
答案 0 :(得分:1)
有几种方法可以做到这一点,我之前已经非常成功地使用过:
假设我们有相同的工厂结构:
angular.module('someApp').factory('SomeFactory', function($http) {
var cache = {};
$http({...some params...})
.success(function(data) {
// ...
cache[key] = data;
});
return {
cache: cache
};
});
我们可以绑定到工厂本身,而不是将items
直接设置为cache[key]
。毕竟,工厂(或服务)只是一个对象:
this.cache = SomeFactory.cache // bind to container which is going to persist
然后在模板中,您只需使用ng-repeat="item in $ctrl.cache[key]"
,它就会自动获得最新的更改。您甚至可以采取额外步骤,直接将服务与this.SomeFactory = SomeFactory
绑定到范围,然后在您的视图中将其用作$ctrl.SomeFactory.cache[key]
。它适用于每个应用程序加载一次的数据结构,或专门为特定控制器创建的服务。
根据您的使用方式,这种方法存在潜在问题。您提到修改数组但由于我们异步覆盖引用,因此可能很难确保这些更改仍然存在。
解决这个问题的另一种方法是稍微修改我们的工厂:
angular.module('someApp').factory('SomeFactory', function($http) {
var cache = {};
cache[key] = []; // initialise an array which we'll use everywhere
$http({...some params...})
.success(function(data) {
// ...
cache[key].push.apply(cache[key], data); // essentially a pushAll
// we could also set cache[key].length = 0 to clear previous data or do something else entirely
});
return {
cache: cache
};
});
如您所见,我们不是替换引用,而是在items
属性引用的同一个数组上运行。这样做的好处是,如果我们以任何方式操作数组(即添加额外的项目),一旦我们收到新的异步数据,我们就可以更灵活地使用它们。
这实际上类似于ngResource使用的方法 - 一旦实际获取数据,集合查询方法将返回一个稍后填写的数组。
我之前使用的最后一种方法是公开数据承诺:
angular.module('someApp').factory('SomeFactory', function($http) {
var cache = {};
var whenReady = $http({...some params...})
.then(function(data) {
// ...
cache[key] = data;
return data;
});
return {
cache: cache,
whenReady: whenReady
};
});
然后在控制器中,只需在解析后分配它:
SomeFactory.whenReady.then(items => {
this.items = items; // or this.items = SomeFactory.cache[key];
});
所有这些都避免了额外的$watch
,但这取决于您的应用最方便的内容。