angular:适合将视图绑定到服务数据

时间:2016-12-06 00:36:33

标签: angularjs

将视图绑定到服务中的数据的正确方法是什么? 我已经看到$ 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 个答案:

答案 0 :(得分:1)

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

选项#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]。它适用于每个应用程序加载一次的数据结构,或专门为特定控制器创建的服务。

根据您的使用方式,这种方法存在潜在问题。您提到修改数组但由于我们异步覆盖引用,因此可能很难确保这些更改仍然存在。

选项#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,但这取决于您的应用最方便的内容。