如何$观看多个variables的angular度变化

如何$scope.$watch在Angular中$scope.$watch多个variables,并在其中一个变化时触发callback。

 $scope.name = ... $scope.age = ... $scope.$watch('???',function(){ //called when name or age changed }) 

UPDATE

Angular现在提供了两个作用域方法$ watchGroup (自1.3)和$ watchCollection 。 那些被@blazemonger和@kargold提及。


这应该独立于types和值:

 $scope.$watch('[age,name]', function () { ... }, true); 

在这种情况下,您必须将第三个参数设置为true。

string连接'age + name'在这样的情况下会失败:

 <button ng-init="age=42;name='foo'" ng-click="age=4;name='2foo'">click</button> 

在用户点击button之前,观看值将是42foo42 + foo ),并在点击42foo4 + 2foo )之后。 所以watch函数不会被调用。 所以最好使用数组expression式,如果你不能确保,这种情况下不会出现。

 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link href="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" rel="stylesheet" /> <script src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script> <script src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script> <script src="http://code.angularjs.org/1.2.0-rc.2/angular.js"></script> <script src="http://code.angularjs.org/1.2.0-rc.2/angular-mocks.js"></script> <script> angular.module('demo', []).controller('MainCtrl', function ($scope) { $scope.firstWatchFunctionCounter = 0; $scope.secondWatchFunctionCounter = 0; $scope.$watch('[age, name]', function () { $scope.firstWatchFunctionCounter++; }, true); $scope.$watch('age + name', function () { $scope.secondWatchFunctionCounter++; }); }); describe('Demo module', function () { beforeEach(module('demo')); describe('MainCtrl', function () { it('watch function should increment a counter', inject(function ($controller, $rootScope) { var scope = $rootScope.$new(); scope.age = 42; scope.name = 'foo'; var ctrl = $controller('MainCtrl', { '$scope': scope }); scope.$digest(); expect(scope.firstWatchFunctionCounter).toBe(1); expect(scope.secondWatchFunctionCounter).toBe(1); scope.age = 4; scope.name = '2foo'; scope.$digest(); expect(scope.firstWatchFunctionCounter).toBe(2); expect(scope.secondWatchFunctionCounter).toBe(2); // This will fail! })); }); }); (function () { var jasmineEnv = jasmine.getEnv(); var htmlReporter = new jasmine.HtmlReporter(); jasmineEnv.addReporter(htmlReporter); jasmineEnv.specFilter = function (spec) { return htmlReporter.specFilter(spec); }; var currentWindowOnload = window.onload; window.onload = function() { if (currentWindowOnload) { currentWindowOnload(); } execJasmine(); }; function execJasmine() { jasmineEnv.execute(); } })(); </script> </head> <body></body> </html> 

http://plnkr.co/edit/2DwCOftQTltWFbEDiDlA?p=preview

PS:

正如@reblace在评论中所述,当然可以访问这些值:

 $scope.$watch('[age,name]', function (newValue, oldValue) { var newAge = newValue[0]; var newName = newValue[1]; var oldAge = oldValue[0]; var oldName = oldValue[1]; }, true); 
 $scope.$watch('age + name', function () { //called when name or age changed }); 

Angular 1.3专门为此提供了$ watchGroup:

https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchGroup

这似乎提供了与expression式数组中的标准$ watch相同的最终结果。 我喜欢它,因为它使代码中的意图更清晰。

有很多方法来观看多个值:

 //angular 1.1.4 $scope.$watchCollection(['foo', 'bar'], function(newValues, oldValues){ // do what you want here }); 

或更新的版本

 //angular 1.3 $scope.$watchGroup(['foo', 'bar'], function(newValues, oldValues, scope) { //do what you want here }); 

阅读官方文档了解更多信息: https : //docs.angularjs.org/api/ng/type/ $ rootScope.Scope

没有人提到这个明显的问题:

 var myCallback = function() { console.log("name or age changed"); }; $scope.$watch("name", myCallback); $scope.$watch("age", myCallback); 

这可能意味着less一点投票。 如果你同时看name + age (为此)和name (其他地方),那么我认为Angular会有效地看两次name ,看看它是不是很脏。

通过名称而不是内联来使用callback可以说是更可读的。 特别是如果你能给它一个比我的例子更好的名字。

你可以用不同的方式观察值,如果你需要:

 $scope.$watch("buyers", myCallback, true); $scope.$watchCollection("sellers", myCallback); 

$watchGroup是很好的,如果你可以使用它,但据我所知,它不会让你观看组成员作为一个集合或与对象相等。

如果您需要在同一个callback函数调用中同时使用这两个expression式的旧值和新值,那么也许其他一些build议的解决scheme更方便一些。