我有一个多步向导,它绑定服务中的数据(wizardStateSvc)。我希望屏幕上有一个totals元素,只要更新了影响总计的向导基值,就会更新。计算有点复杂(比我的示例中显示的更多)所以我想让它在控制器中执行。我认为$ watch会对此有用,但是发生的事情是$ watch函数在初始化期间被调用一次,并且在我更新项目时从不触发。如何让这个$ watch正确触发?
总计控制器:
myApp.controller('wizardTotalsCtrl', ['wizardStateSvc', '$scope', function (wizardStateSvc, $scope) {
$scope.products= wizardStateSvc.quote.products;
$scope.$watch(function() { return wizardStateSvc.quote.products; }, function(products) {
var total= 0;
products.forEach(function(product) {
total += product.price * (1 - (product.dealerDiscount * 0.01)) * product.quantity;
});
$scope.baseTotal = total;
});
}])
国家服务:
myApp.service("wizardStateSvc", [function () {
var quote = {
products: [],
options: {},
customer: {},
shipping: {},
other: {}
}
return {
quote: quote
}
}]);
答案 0 :(得分:2)
如果唯一可以改变的是products
数组的内容,即可以从数组中插入或删除产品但是price
NOT 更改,然后使用$scope.$watchCollection
。代码与您的代码相同,只需将$watch
替换为$watchCollection
。
理由:$watch
检查是否平等;由于products
数组本身不会改变(即products at time t1 === products at time t2
),因此永远不会触发监视。另一方面,$watchCollection
监视数组的内容,因此在这种情况下它就是你想要的。
如果产品的价格也可能发生变化,则需要更高的成本$scope.$watch(...,...,true)
。第3个参数的true
表示深度监视,即遍历对象层次结构并检查每个嵌套属性。查看docs。
答案 1 :(得分:0)
您的手表可以观看阵列产品'。当它被初始化时,products是对数组的引用,当你添加值时,产品仍然是对同一个数组的引用,它只是不同的数组内容,所以确实存在没有理由让你的手表再次调用该功能。这个问题有两个解决方案:
不太好的解决方案:观察产品的长度,这样只要产品长度发生变化,手表就会被调用。
$scope.$watch(function() { return wizardStateSvc.quote.products.length; }, ...);
在添加一个项目并在之后立即删除另一个项目的用例中存在问题。如果在此操作之前,手表的值为x,则在您执行操作后它将为x,因此无法调用。
更好的解决方案:使用手表集合,它也可以处理长度不看的用例。
$scope.$watchCollection('products', ...);
从文档(滚动到$ watchCollection部分):
https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope