Ответ 1
$наблюдать() - это метод на Attributes объект и, как таковой, его можно использовать только для наблюдения/просмотра изменения стоимости атрибута DOM. Он используется только внутри внутренних директив. Используйте $наблюдать, когда вам нужно наблюдать/смотреть атрибут DOM, который содержит интерполяцию (т.е. {{}}).
Например, attr1="Name: {{name}}"
, затем в директиве: attrs.$observe('attr1', ...)
.
(Если вы попробуете scope.$watch(attrs.attr1, ...)
, это не сработает из-за {{}} s - вы получите undefined
.) Используйте $watch для всего остального.
$watch() сложнее. Он может наблюдать/смотреть "выражение", где выражение может быть либо функцией, либо строкой. Если выражение является строкой, оно $parse 'd (т.е. Оценивается как выражение Angular) в функцию. (Эта функция называется каждым циклом дайджеста.) Строковое выражение не может содержать {{}}. $watch - это метод на объекте Scope, поэтому его можно использовать/вызывать везде, где у вас есть доступ к объекту области видимости, следовательно, в
- контроллер - любой контроллер - один, созданный с помощью ng-view, ng-controller или директивного контроллера.
- связующая функция в директиве, так как она также имеет доступ к области видимости
Поскольку строки оцениваются как выражения Angular, $watch часто используется, когда вы хотите наблюдать/наблюдать за свойством model/scope. Например, attr1="myModel.some_prop"
, затем в функции контроллера или ссылки: scope.$watch('myModel.some_prop', ...)
или scope.$watch(attrs.attr1, ...)
(или scope.$watch(attrs['attr1'], ...)
).
(Если вы попробуете attrs.$observe('attr1')
, вы получите строку myModel.some_prop
, которая, вероятно, не то, что вы хотите.)
Как указано в комментариях к ответу @PrimosK, все $observes и $watch проверяются каждый цикл .
Директивы с изолированными областями более сложны. Если используется синтаксис "@" , вы можете $наблюдать или $смотреть атрибут DOM, содержащий интерполяцию (т.е. {{}}). (Причина, по которой он работает с $watch, заключается в том, что синтаксис "@" делает интерполяцию для нас, поэтому $watch видит строку без {{}}.) Чтобы было легче запомнить, что использовать, я также предлагаю использовать $observ для этого случая.
Чтобы проверить все это, я написал Plunker, который определяет две директивы. Один (d1
) не создает новую область, другой (d2
) создает область выделения. Каждая директива имеет те же шесть атрибутов. Каждый атрибут - $watch'd и $watch'ed.
<div d1 attr1="{{prop1}}-test" attr2="prop2" attr3="33" attr4="'a_string'"
attr5="a_string" attr6="{{1+aNumber}}"></div>
Посмотрите на журнал консоли, чтобы увидеть различия между $obs и $watch в функции привязки. Затем нажмите ссылку и посмотрите, какие $наблюдаются и $watches запускаются изменениями свойств, сделанными обработчиком кликов.
Обратите внимание, что при запуске функции ссылки все атрибуты, содержащие {{}}, еще не оценены (поэтому, если вы попытаетесь изучить атрибуты, вы получите undefined
). Единственный способ увидеть интерполированные значения - использовать $observ (или $watch, если использовать область выделения с помощью "@" ). Следовательно, получение значений этих атрибутов является асинхронной. (И поэтому нам нужны функции $watch и $watch.)
Иногда вам не нужны $watch или $watch. Например, если ваш атрибут содержит число или логическое значение (а не строку), просто оцените его один раз: attr1="22"
, а затем, скажем, в вашей функции связывания: var count = scope.$eval(attrs.attr1)
. Если это просто постоянная строка – attr1="my string"
– то просто используйте attrs.attr1
в своей директиве (нет необходимости в $eval()).
См. также Сообщение группы Vojta google о выражении $watch.