$ obs () là một phương thức trênđối tượng Thuộc tính và do đó, nó chỉ có thể được sử dụng để quan sát / theo dõi sự thay đổi giá trị của thuộc tính DOM. Nó chỉ được sử dụng / được gọi bên trong các chỉ thị. Sử dụng $ obs khi bạn cần quan sát / xem thuộc tính DOM có chứa phép nội suy (nghĩa là {{}} 's).
Ví dụ,attr1="Name: {{name}}"
sau đó trong một chỉ thị :attrs.$observe('attr1', ...)
.
(Nếu bạn thửscope.$watch(attrs.attr1, ...)
nó sẽ không hoạt động vì {{}} s - bạn sẽ nhận đượcundefined
.) Sử dụng $ watch cho mọi thứ khác.
$ watch () phức tạp hơn. Nó có thể quan sát / xem một "biểu thức", trong đó biểu thức có thể là hàm hoặc chuỗi. Nếu biểu thức là một chuỗi, nó là $ parse 'd (nghĩa là được đánh giá là biểu thức Angular ) thành một hàm. (Chính hàm này được gọi là mỗi chu kỳ phân loại.) Biểu thức chuỗi không thể chứa {{}} 's. $ watch là một phương thức trênđối tượng Phạm vi , vì vậy nó có thể được sử dụng / gọi bất cứ nơi nào bạn có quyền truy cập vào một đối tượng phạm vi, do đó trong
- một bộ điều khiển - bất kỳ bộ điều khiển nào - một bộ điều khiển được tạo thông qua ng-view, ng-controller hoặc bộ điều khiển chỉ thị
- một chức năng liên kết trong một lệnh, vì điều này cũng có quyền truy cập vào một phạm vi
Vì các chuỗi được đánh giá là biểu thức góc, $ watch thường được sử dụng khi bạn muốn quan sát / xem thuộc tính mô hình / phạm vi. Ví dụ, attr1="myModel.some_prop"
sau đó trong một bộ điều khiển hoặc chức năng liên kết: scope.$watch('myModel.some_prop', ...)
hoặc scope.$watch(attrs.attr1, ...)
(hoặc scope.$watch(attrs['attr1'], ...)
).
(Nếu bạn thử, attrs.$observe('attr1')
bạn sẽ nhận được chuỗi myModel.some_prop
, đó có thể không phải là điều bạn muốn.)
Như đã thảo luận trong các nhận xét về câu trả lời của @ PrimosK, tất cả các đồng hồ $ quan sát và $ được kiểm tra mỗi chu kỳ tiêu hóa .
Chỉ thị với phạm vi cách ly phức tạp hơn. Nếu cú pháp '@' được sử dụng, bạn có thể $ obs hoặc $ xem thuộc tính DOM có chứa phép nội suy (nghĩa là {{}} '). (Lý do nó hoạt động với $ watch là vì cú pháp '@' thực hiện phép nội suy cho chúng ta, do đó $ watch nhìn thấy một chuỗi không có {{}} 's.) $ quan sát cho trường hợp này cũng.
Để giúp kiểm tra tất cả những điều này, tôi đã viết một Plunker xác định hai chỉ thị. Một ( d1
) không tạo ra một phạm vi mới, còn lại ( d2
) tạo ra một phạm vi cô lập. Mỗi chỉ thị có sáu thuộc tính giống nhau. Mỗi thuộc tính là cả $ obs'd và $ watch'ed.
<div d1 attr1="{{prop1}}-test" attr2="prop2" attr3="33" attr4="'a_string'"
attr5="a_string" attr6="{{1+aNumber}}"></div>
Nhìn vào nhật ký giao diện điều khiển để thấy sự khác biệt giữa $ obs và $ watch trong chức năng liên kết. Sau đó nhấp vào liên kết và xem $ quan sát và đồng hồ $ nào được kích hoạt bởi các thay đổi thuộc tính được thực hiện bởi trình xử lý nhấp chuột.
Lưu ý rằng khi hàm liên kết chạy, mọi thuộc tính có chứa {{}} vẫn chưa được đánh giá (vì vậy nếu bạn cố kiểm tra các thuộc tính, bạn sẽ nhận được undefined
). Cách duy nhất để xem các giá trị được nội suy là sử dụng $ obs (hoặc $ watch nếu sử dụng phạm vi cô lập với '@'). Do đó, nhận các giá trị của các thuộc tính này là một hoạt động không đồng bộ . (Và đây là lý do tại sao chúng ta cần các chức năng $ obs và $ watch.)
Đôi khi bạn không cần $ obs hoặc $ watch. Ví dụ: nếu thuộc tính của bạn chứa một số hoặc boolean (không phải là một chuỗi), chỉ cần đánh giá nó một lần : attr1="22"
, sau đó, giả sử, chức năng liên kết của bạn : var count = scope.$eval(attrs.attr1)
. Nếu nó chỉ là một chuỗi không đổi - attr1="my string"
- thì chỉ cần sử dụng attrs.attr1
trong lệnh của bạn (không cần $ eval ()).
Xem thêm bài viết trên nhóm google của Vojta về $ biểu thức đồng hồ.