如何$观看多个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之前,观看值将是42foo
( 42
+ foo
),并在点击42foo
( 4
+ 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更方便一些。