Cách $scope.$watch
nhiều biến trong Góc và kích hoạt gọi lại khi một trong số chúng đã thay đổi.
$scope.name = ...
$scope.age = ...
$scope.$watch('???',function(){
//called when name or age changed
})
Cách $scope.$watch
nhiều biến trong Góc và kích hoạt gọi lại khi một trong số chúng đã thay đổi.
$scope.name = ...
$scope.age = ...
$scope.$watch('???',function(){
//called when name or age changed
})
CẬP NHẬT
góc Mời nay là hai phương pháp phạm vi $watchGroup (từ 1.3) và $watchCollection. Những người đã được đề cập bởi @blazemonger và @kargold.
này nên hoạt động độc lập với các chủng loại và giá trị:
$scope.$watch('[age,name]', function() { ... }, true);
Bạn cần phải thiết lập các tham số thứ ba là true trong trường hợp này.
Chuỗi nối 'age + name'
sẽ thất bại trong một trường hợp như thế này:
<button ng-init="age=42;name='foo'" ng-click="age=4;name='2foo'">click</button>
Trước khi người dùng nhấp chuột vào nút giá trị quan sát sẽ là 42foo
(42
+ foo
) và sau khi nhấp chuột 42foo
(4
+ 2foo
) . Vì vậy, chức năng đồng hồ sẽ không được gọi. Vì vậy, tốt hơn sử dụng một biểu thức mảng nếu bạn không thể đảm bảo, rằng trường hợp như vậy sẽ không xuất hiện.
<!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:
Như đã trình bày bởi @reblace trong một chú thích, nó là tất nhiên có thể truy cập các giá trị:
$scope.$watch('[age,name]', function (newValue, oldValue) {
var newAge = newValue[0];
var newName = newValue[1];
var oldAge = oldValue[0];
var oldName = oldValue[1];
}, true);
Plunker không hoạt động –
@ Ajax3.14: Chính xác thì những gì không hoạt động? Tôi không thể tái tạo vấn đề đó. Nó có thể được, mà bạn thấy đầu ra jasmie "Thất bại 1 spec"? Đó sẽ là đầu ra mong đợi, bởi vì kiểm tra không thành công (xem chú thích trong mã nguồn của bài kiểm tra). – stofl
Câu trả lời này đã giúp tôi, cảm ơn! Vẻ đẹp của phương pháp này là bạn có thể truy cập newValue/oldValue như các phần tử của mảng đã xem (ví dụ: newValue [0], newValue [1] và oldValue [0], oldValue [1]) – reblace
$scope.$watch('age + name', function() {
//called when name or age changed
});
Điều này sẽ làm việc do JS concatinating chúng như Strings. Câu trả lời hay và btw đúng. – Heinrich
Để bất cứ ai tìm câu trả lời cho cùng một câu hỏi - câu trả lời của tôi là không chính xác, câu trả lời này là đúng. – callmekatootie
Ngoài ra hãy chắc chắn trong trường hợp này không sử dụng các đối số 'newValue' và' oldValue' mà góc chuyển vào gọi lại vì chúng sẽ là kết quả nối và không chỉ là trường đã được thay đổi. –
góc 1.3 cung cấp $ watchGroup đặc biệt cho mục đích này:
https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchGroup
Điều này dường như cung cấp kết quả cuối cùng giống như đồng hồ $ tiêu chuẩn trên một mảng biểu thức. Tôi thích nó vì nó làm cho ý định rõ ràng hơn trong mã.
Có nhiều cách để xem nhiều giá trị:
//angular 1.1.4
$scope.$watchCollection(['foo', 'bar'], function(newValues, oldValues){
// do what you want here
});
trở lên phiên bản mới
//angular 1.3
$scope.$watchGroup(['foo', 'bar'], function(newValues, oldValues, scope) {
//do what you want here
});
đọc doc chính thức để biết thêm thông tin: https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope
Không ai có đã đề cập rõ ràng:
var myCallback = function() { console.log("name or age changed"); };
$scope.$watch("name", myCallback);
$scope.$watch("age", myCallback);
Điều này có thể có nghĩa là ít bỏ phiếu hơn một chút. Nếu bạn xem cả hai name + age
(cho điều này) và name
(ở nơi khác) thì tôi giả sử Góc sẽ xem xét hiệu quả name
hai lần để xem liệu nó có bẩn không.
Có thể đọc được nhiều hơn để sử dụng gọi lại theo tên thay vì gạch chân nó. Đặc biệt là nếu bạn có thể cho nó một cái tên tốt hơn trong ví dụ của tôi.
Và bạn có thể xem các giá trị theo những cách khác nhau nếu bạn cần phải:
$scope.$watch("buyers", myCallback, true);
$scope.$watchCollection("sellers", myCallback);
$watchGroup
là tốt đẹp nếu bạn có thể sử dụng nó, nhưng như xa như tôi có thể nói, nó không cho phép bạn xem các nhóm thành viên như một bộ sưu tập hoặc với sự bình đẳng đối tượng.
Nếu bạn cần các giá trị cũ và mới của cả biểu thức bên trong một và giống nhau gọi hàm callback, thì có lẽ một số các giải pháp đề xuất khác là thuận tiện hơn.
nó gọi chức năng gọi lại ngay cả lần đầu tiên khi bộ điều khiển của tôi được nạp? sao tôi không thể dừng nó để gọi lần đầu tiên khi bộ điều khiển được nạp? –
Có [một bài đăng blog rất hay của Ben Nadel] (http://www.bennadel.com/blog/2566-Scope-watch-vs-watchCollection-In-AngularJS.htm) về chủ đề của $ watch vs $ watchCollection bạn có thể thấy hữu ích. –