Angularjs 角度:适合将视图绑定到服务数据

Angularjs 角度:适合将视图绑定到服务数据,angularjs,Angularjs,将视图绑定到服务数据的正确方法是什么我发现$watch是不受欢迎的 我有一个视图,用于呈现来自服务的数组中的项目 服务将定期从服务器刷新其数据 $http({...some params...}) .success(function(data) { cache[key] = data; }); 在视图控制器中,数据是公开的: this.items = SomeFactory.cache[key] 视图具有约束力: ng-repeat="item in $ctrl.items" 我

将视图绑定到服务数据的正确方法是什么我发现$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()”
)绑定它,它确实可以工作,但我如何修改该项?从性能角度看,我不知道这是否比直接绑定效率低?

有几种方法可以做到这一点,我以前已经非常成功地使用过:

选项1-单向“向上”绑定 假设我们有相同的工厂结构:

angular.module('someApp').factory('SomeFactory', function($http) {
  var cache = {};

  $http({...some params...})
    .success(function(data) {
      // ...
      cache[key] = data;
    });

  return {
    cache: 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]
。它适用于每个应用程序加载一次的数据结构,或者专门为特定控制器制作的服务

这种方法存在一个潜在的问题,这取决于您如何使用它。您提到修改数组,但由于我们异步重写引用,因此可能很难确保这些更改保持不变

选项2-修改阵列,而不是替换阵列 解决这个问题的另一种方法是稍微修改一下我们的工厂:

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使用的方法—收集查询方法返回一个数组,该数组在实际获取数据之后填充

选项3-公开承诺 我之前使用的最后一种方法是公开数据的承诺:

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
,但这取决于什么对你的应用程序最方便。

Hmmm,你确定它不会更新吗?我已经创造了一个似乎是这样工作的。还有什么其他原因可能会导致这个问题吗?嗯,很有意思。我会再试试的。也许是两层物体引起的不,你说得对,我是个哑巴。您使用它的方式与plunker有点不同。我会写一个关于我们如何处理类似用例的答案。谢谢你的回答。至于选项#2,基本上复制所有元素的性能影响是什么?我们不是复制元素,我们基本上是调用
cache[key]。在循环中推送
,所以我们甚至没有创建新数组。就性能影响而言,最好的方法是分析——这很可能无关紧要,除非你经常这样做。我会说,选择哪个解决方案是最可维护的,然后在分析之后决定是否存在问题。