修改了绑定到控制器范围的工厂中的数据,它不会更新

时间:2014-08-12 23:41:04

标签: javascript angularjs angularjs-scope angularjs-factory

我有一个非常简单的例子

(也可在此小提琴上找到:http://jsfiddle.net/depov5w6/

我有两个工厂,一个返回一个带有属性' data'的对象(绑定到控制器的范围),另一个工厂有两个方法:populateData和pushData。 populateData将dataSource.data的值设置为新值。 pushData将一个新值推送到dataSource.data

angular.module("app",[])
  .factory('dataSource', function() { 
    return {
      data: ["Init Data"]
    };
  })
  .factory('dataModifier', function(dataSource) { 
    return {
      populateData: function() {
        dataSource.data = ["data from populateData"];
      },
      pushData: function() {
        dataSource.data.push("new data from push data");
      }
    }
  })
  .controller('dataCtrl', function($scope, dataSource, dataModifier) {
    $scope.data = dataSource.data;
    $scope.populateData = dataModifier.populateData;
    $scope.pushData = dataModifier.pushData;
  })

在我看来,我有一个调用pushData的按钮和另一个调用populateData的按钮。我还会显示$ scope.data

<div ng-app="app">
  <div ng-controller="dataCtrl" class="container">
    <p>Data: {{data}}</p>
    <button ng-click="pushData()">Push Data</button>
    <button ng-click="populateData()">Set Data To New Value</button>
  </div>
</div>

如果您查看小提琴,如果单击“推送数据”按钮,新值将被推送到阵列上。但是,如果您单击“将数据设置为新值”,则不会发生任何事情,并且后续单击以推送数据不会执行任何操作。我想我明白,当你点击填充数据时,你会丢失对$ scope.data绑定的数组的引用,但为什么$ scope没有意识到dataSource.data有一个新值?我该如何解决这个问题?我尝试将数据作为私有变量,并使用getter和setter,但这没有做任何事情。

我很欣赏任何见解。

3 个答案:

答案 0 :(得分:6)

不是将数据分配给范围,而是将整个数据源对象分配给范围&amp;然后使用它。

类似于:http://jsfiddle.net/depov5w6/1/

.controller('dataCtrl', function($scope, dataSource, dataModifier) {
    $scope.dataSource = dataSource;
    $scope.populateData = dataModifier.populateData;
    $scope.pushData = dataModifier.pushData;
});
<div ng-app="app">
   <div ng-controller="dataCtrl" class="container">
   <p>Data: {{dataSource.data}}</p>
   <button ng-click="pushData()">Push Data</button>
   <button ng-click="populateData()">Set Data To New Value</button>
</div>

这件事有效的原因是因为角度的脏检查工作方式。它比较整个对象以检测是否有任何变化。将变量绑定到作用域时,它会在其上创建监视。如果将对象分配给作用域,则它会检查对象的值以监视属性值的任何更改。所以你需要把手表放在对象的属性上。

答案 1 :(得分:1)

  

我想我明白,当你点击填充数据时,你会丢失对$ scope.data绑定的数组的引用,但是为什么$ scope没有意识到dataSource.data有一个新值?

你是对的。在创建控制器之前(在您有机会单击按钮之前),它会将$ scope.data指向内存中的一个列表,该列表也由dataSource.data指向。您的populateData()函数告诉dataSource.data指向一个全新的列表..但它并不告诉$ scope.data停止指向旧的列表。

您可以使用$scope.$watch()告知引用dataSource.data何时更改,然后更新$scope.data

.controller('dataCtrl', function($scope, dataSource, dataModifier) {
  $scope.dataSource = dataSource;
  $scope.$watch('dataSource.data', function(data) {
      $scope.data = data;
  });
  $scope.populateData = dataModifier.populateData;
  $scope.pushData = dataModifier.pushData;
})

答案 2 :(得分:0)

您必须更改下面的populateData方法

  populateData: function() {
    dataSource.data. splice(dataSource.data,dataSource.data.length);
    dataSource.data.push("data from populateData");
  }

Demo