AngularJS: Разница между методами $ наблюдений и $ наблюдений

338

Я знаю, что как Watchers, так и Observers вычисляются, как только что-то в $scope изменяется в AngularJS. Но не мог понять, что именно представляет собой различие между ними.

Мое первоначальное понимание заключается в том, что Observers вычисляются для выражений angular, которые являются условиями на стороне HTML, где в качестве Watchers выполняется при выполнении функции $scope.$watch(). Думаю ли я правильно?

  • 1
    Ваше редактирование не помогает и немного противодействует. Пожалуйста, будьте внимательны к другим, приходящим сюда за реальной помощью.
  • 0
    @smalone изменился. Спасибо и извините!
Показать ещё 1 комментарий
Теги:

3 ответа

580
Лучший ответ

$наблюдать() - это метод на 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.

  • 13
    Отличное объяснение! +1
  • 52
    Это более полезно, чем официальные документы Angular! Спасибо!
Показать ещё 13 комментариев
19

Если я правильно понимаю ваш вопрос, вы спрашиваете, в чем разница, если вы регистрируете обратный вызов слушателя с помощью $watch или если вы делаете это с помощью $observe.

Обратный вызов с $watch запускается при выполнении $digest. Пожалуйста, посмотрите docs для получения дополнительной информации.

Обратный вызов, зарегистрированный с помощью $observe, вызывается при изменении значений атрибутов, содержащих интерполяцию (например, attr="{{notJetInterpolated}}").


Внутри директивы вы можете использовать оба из них очень похожим образом:

    attrs.$observe('attrYouWatch', function() {
         // body
    });

или

    scope.$watch(attrs['attrYouWatch'], function() {
         // body
    });
  • 3
    На самом деле, поскольку каждое изменение отражается в фазе $digest , можно с уверенностью предположить, что обратный вызов $observe будет вызываться в $digest . И обратный вызов $watch также будет вызываться в $digest но всякий раз, когда значение изменяется. Я думаю, что они делают ту же самую работу: «наблюдайте за выражением, вызывайте обратный вызов, значение меняется». Разница в ключевых словах, возможно, просто синтаксический сахар, чтобы не запутывать разработчика.
  • 1
    @ fastreload, я полностью согласен с твоим комментарием .. Красиво написано!
Показать ещё 4 комментария
1

Я думаю, это довольно очевидно:

  • $observ используется для связывания функции директив.
  • $watch используется для просмотра любых изменений в своих значениях.

Имейте в виду: обе функции имеют два аргумента,

$observe/$watch(value : string, callback : function);
  • Значение: всегда является строковой ссылкой на наблюдаемый элемент (имя переменной области видимости или имя атрибута директивы, подлежащего просмотру)
  • callback: функция, которая должна быть выполнена из формы function (oldValue, newValue)

Я сделал plunker, так что вы действительно можете понять их использование. Я использовал аналогию Хамелеона, чтобы упростить ее изображение.

  • 2
    Это довольно очевидно о его использовании. Но почему был вопрос. Марк подвел итог красиво.
  • 3
    Я думаю, что параметры могут быть переключены - кажется, что они передают newValue, а затем oldValue, в attrs. $ Наблюдаем (). , ,

Ещё вопросы

Сообщество Overcoder
Наверх
Меню