Bằng cách kiểm tra bẩn $scopeđối tượng
Angular duy trì một đơn giản arraycủa người theo dõi trong các $scopeđối tượng. Nếu bạn kiểm tra bất kỳ $scopebạn sẽ thấy rằng nó có chứa một cuộc arraygọi $$watchers.
Mỗi người theo dõi là một trong objectđó có những thứ khác
- Một biểu hiện mà người theo dõi đang theo dõi. Đây có thể chỉ là một
attributecái tên, hoặc một cái gì đó phức tạp hơn.
- Một giá trị được biết đến cuối cùng của biểu thức. Điều này có thể được kiểm tra đối với giá trị tính toán hiện tại của biểu thức. Nếu các giá trị khác nhau, trình theo dõi sẽ kích hoạt chức năng và đánh dấu
$scopelà bẩn.
- Một chức năng sẽ được thực hiện nếu người theo dõi bị bẩn.
Người theo dõi được định nghĩa như thế nào
Có nhiều cách khác nhau để định nghĩa một người theo dõi trong AngularJS.
Bạn có thể rõ ràng $watchmột attributetrên $scope.
$scope.$watch('person.username', validateUnique);
Bạn có thể đặt một {{}}phép nội suy trong mẫu của bạn (một trình theo dõi sẽ được tạo cho bạn trên hiện tại $scope).
<p>username: {{person.username}}</p>
Bạn có thể yêu cầu một chỉ thị như ng-modelxác định người theo dõi cho bạn.
<input ng-model="person.username" />
Các $digestchu kỳ kiểm tra tất cả sát chống lại giá trị cuối cùng của họ
Khi chúng ta tương tác với AngularJS thông qua các kênh thông thường (ng-model, ng-repeat, v.v.), một chu trình tiêu hóa sẽ được kích hoạt bởi lệnh.
Một chu trình tiêu hóa là một giao dịch sâu đầu tiên $scopevà tất cả các con của nó . Đối với mỗi $scope object, chúng tôi lặp lại qua nó $$watchers arrayvà đánh giá tất cả các biểu thức. Nếu giá trị biểu thức mới khác với giá trị đã biết cuối cùng, chức năng của trình xem sẽ được gọi. Hàm này có thể biên dịch lại một phần của DOM, tính toán lại một giá trị trên $scope, kích hoạt một AJAX request, bất cứ điều gì bạn cần nó để làm.
Mọi phạm vi đều đi qua và mọi biểu thức đồng hồ được đánh giá và kiểm tra so với giá trị cuối cùng.
Nếu một người theo dõi được kích hoạt, $scopelà bẩn
Nếu một người theo dõi được kích hoạt, ứng dụng sẽ biết có gì đó đã thay đổi và $scopeđược đánh dấu là bẩn.
Các chức năng của người theo dõi có thể thay đổi các thuộc tính khác trên $scopehoặc trên cha mẹ $scope. Nếu một $watcherchức năng đã được kích hoạt, chúng tôi không thể đảm bảo rằng các chức năng khác của chúng tôi $scopevẫn sạch và vì vậy chúng tôi thực hiện lại toàn bộ chu trình phân loại.
Điều này là do AngularJS có ràng buộc hai chiều, do đó dữ liệu có thể được truyền ngược lên $scopecây. Chúng tôi có thể thay đổi một giá trị ở mức cao hơn $scopeđã được tiêu hóa. Có lẽ chúng ta thay đổi một giá trị trên $rootScope.
Nếu $digestbẩn, chúng tôi thực hiện lại toàn bộ $digestchu trình
Chúng tôi liên tục lặp qua $digestchu trình cho đến khi chu trình tiêu hóa hoàn toàn sạch (tất cả các $watchbiểu thức có cùng giá trị như trong chu kỳ trước) hoặc chúng tôi đạt đến giới hạn tiêu hóa. Theo mặc định, giới hạn này được đặt ở mức 10.
Nếu chúng tôi đạt đến giới hạn tiêu hóa, AngularJS sẽ phát sinh lỗi trong bảng điều khiển:
10 $digest() iterations reached. Aborting!
Thông báo khó về máy nhưng dễ với nhà phát triển
Như bạn có thể thấy, mỗi khi có gì đó thay đổi trong ứng dụng AngularJS, AngularJS sẽ kiểm tra từng người theo dõi trong $scopehệ thống phân cấp để xem cách phản hồi. Đối với một nhà phát triển, đây là một lợi ích lớn về năng suất, vì bây giờ bạn cần phải viết gần như không có mã nối dây, AngularJS sẽ chỉ thông báo nếu một giá trị đã thay đổi và làm cho phần còn lại của ứng dụng phù hợp với thay đổi.
Từ quan điểm của máy mặc dù điều này rất kém hiệu quả và sẽ làm chậm ứng dụng của chúng tôi nếu chúng tôi tạo quá nhiều người theo dõi. Misko đã trích dẫn một con số khoảng 4000 người theo dõi trước khi ứng dụng của bạn cảm thấy chậm trên các trình duyệt cũ hơn.
Giới hạn này là dễ dàng để đạt được nếu bạn ng-repeatvượt quá lớn JSON arraychẳng hạn. Bạn có thể giảm thiểu việc này bằng các tính năng như ràng buộc một lần để biên dịch mẫu mà không cần tạo trình theo dõi.
Làm thế nào để tránh tạo quá nhiều người theo dõi
Mỗi lần người dùng của bạn tương tác với ứng dụng của bạn, mỗi người theo dõi trong ứng dụng của bạn sẽ được đánh giá ít nhất một lần. Một phần lớn của việc tối ưu hóa ứng dụng AngularJS là giảm số lượng người theo dõi trong $scopecây của bạn . Một cách dễ dàng để làm điều này là với một lần ràng buộc .
Nếu bạn có dữ liệu hiếm khi thay đổi, bạn chỉ có thể liên kết dữ liệu đó một lần bằng cách sử dụng cú pháp :: như vậy:
<p>{{::person.username}}</p>
hoặc là
<p ng-bind="::person.username"></p>
Liên kết sẽ chỉ được kích hoạt khi mẫu chứa được hiển thị và dữ liệu được tải vào $scope.
Điều này đặc biệt quan trọng khi bạn có một ng-repeatvới nhiều mặt hàng.
<div ng-repeat="person in people track by username">
{{::person.username}}
</div>