我有一个非常简单的例子
(也可在此小提琴上找到: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,但这没有做任何事情。
我很欣赏任何见解。
答案 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");
}