Как $watch несколько переменных изменений в угловой [дубликат]
этот вопрос уже есть ответ здесь:
смотреть несколько $ scope атрибуты
11 ответов
Как $scope.$watch несколько переменных в угловой, и триггер обратного вызова, когда один из них изменился.
$scope.name = ...
$scope.age = ...
$scope.$watch('???',function(){
//called when name or age changed
})
5 ответов:
обновление
Angular предлагает теперь два метода области $watchGroup (начиная с 1.3) и $watchCollection. Они были упомянуты @blazemonger и @kargold.
это должно работать независимо от типов и значений:
$scope.$watch('[age,name]', function () { ... }, true);вы должны установить третий параметр true в этом случае.
конкатенация строк
'age + name'потерпит неудачу в случае, как это:<button ng-init="age=42;name='foo'" ng-click="age=4;name='2foo'">click</button>прежде чем пользователь нажмет кнопку, наблюдаемое значение будет
42foo(42+foo) и после щелчка42foo(4+2foo). Таким образом, функция часов не будет вызвана. Поэтому лучше использовать выражение массива, если вы не можете гарантировать, что такой случай не появится.<!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);
Angular 1.3 предоставляет $ watchGroup специально для этой цели:
https://docs.angularjs.org/api/ng/type/$rootScope. Scope#$watchGroup
Это, кажется, обеспечивает тот же конечный результат, что и стандартный $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);это может означать, немного меньше опроса. Если вы смотрите оба
name + age(для этого) иname(в другом месте) тогда я предполагаю, что угловой будет эффективно смотреть наnameдважды, чтобы увидеть, если это грязно.возможно, более читаемым является использование обратного вызова по имени вместо его вставки. Особенно, если вы можете дать ему имя получше, чем в моем примере.
и вы можете смотреть значения по-разному, если вам нужно к:
$scope.$watch("buyers", myCallback, true); $scope.$watchCollection("sellers", myCallback);
$watchGroupхорошо, если вы можете использовать его, но, насколько я могу судить, он не позволяет вам смотреть на членов группы как на коллекцию или с равенством объектов.Если вам нужны старые и новые значения и выражения внутри одного и того же вызова функции обратного вызова, то, возможно, некоторые из других предложенных решений более удобны.
Comments