2013-02-14 4 views
359

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

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

+1

Ваше изменение не помогает и немного противоречит. Пожалуйста, будьте внимательны к тому, что другие приходят сюда для реальной помощи. – smalone

+0

@smalone изменен. Спасибо и извините! – Abilash

+0

Не беспокойтесь. Спасибо за исправление. – smalone

ответ

587

$observe() является метод на Attributes объекта, и как таковой, его можно использовать только для наблюдения/просмотра изменения значения атрибута DOM. Он используется только внутри внутренних директив. Используйте $ наблюдать, когда вам нужно наблюдать/смотреть атрибут DOM, который содержит интерполяцию (т. Е. {{}}).
Например, attr1="Name: {{name}}", а затем в директиве: attrs.$observe('attr1', ...).
(Если вы попробуете scope.$watch(attrs.attr1, ...), это не сработает из-за {{}} s - вы получите undefined.) Используйте $ watch для всего остального.

$watch() сложнее. Он может наблюдать/смотреть «выражение», где выражение может быть либо функцией, либо строкой. Если выражение представляет собой строку, то оно равно $parse 'd (т. Е. Оценивается как Angular expression) в функцию. (Эта функция называется каждым циклом дайджеста.) Строковое выражение не может содержать {{}}. $ Часы метод на Scope объекта, поэтому он может быть использован/вызывается везде, где у вас есть доступ к объекту области видимости, поэтому в

  • контроллера - любой контроллер - один созданный с помощью нг ракурса, нг -controller или контроллер директивы
  • функция связывания в директиве, так как это имеет доступ к области применения, а также

поскольку строки оцениваются как Angular выражения, $ часы часто используется, когда вы хотите, чтобы наблюдать/посмотреть свойство модели/области. Например, attr1="myModel.some_prop", затем в контроллере или функции связи: scope.$watch('myModel.some_prop', ...) или scope.$watch(attrs.attr1, ...) (или scope.$watch(attrs['attr1'], ...)).
(Если вы попробуете attrs.$observe('attr1'), вы получите строку myModel.some_prop, которая, вероятно, не то, что вы хотите.)

Как уже говорилось в комментариях к @ PrimosK, все $ watches и $ watch проверяются каждые digest cycle.

Директивы с изолированными областями сложнее. Если используется синтаксис «@», вы можете $ наблюдать за или $ watch атрибутом DOM, который содержит интерполяцию (т. Е. {{}}). (Причина, по которой он работает с $ watch, заключается в том, что синтаксис «@» делает для нас interpolation, поэтому $ watch видит строку без {{}}.) Чтобы было легче запомнить, что использовать, когда я предлагаю использовать $ наблюдают и за этот случай.

Чтобы проверить все это, я написал 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> 

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

Обратите внимание, что при запуске функции ссылки все атрибуты, содержащие {{}}, еще не оценены (поэтому, если вы попытаетесь изучить атрибуты, вы получите undefined). Единственный способ увидеть интерполированные значения - использовать $ observ (или $ watch, если использовать область выделения с помощью «@»). Следовательно, получение значений этих атрибутов является асинхронной операцией . (И поэтому нам нужны функции $ watch и $ watch.)

Иногда вам не нужны $ watch или $ watch. Например, если ваш атрибут содержит число или логическое значение (а не строку), просто оцените его один раз: attr1="22", а затем, скажем, в вашей ссылочной функции: var count = scope.$eval(attrs.attr1). Если это просто постоянная строка – attr1="my string" –, тогда просто используйте attrs.attr1 в своей директиве (нет необходимости в $ eval()).

См. Также Vojta's google group post около $ watch выражения.

+12

Отличное объяснение! +1 – PrimosK

+51

Это более полезно, чем официальные угловые документы! Благодаря! –

+4

Отличный ответ! У вас есть идея, почему 'ng-src/ng-href' использовать' attr. $ Observ' вместо 'scope. $ Watch' тогда? – okm

20

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

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

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


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

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

или

scope.$watch(attrs['attrYouWatch'], function() { 
     // body 
    }); 
+3

Фактически, поскольку каждое изменение отражается в фазе '$ digest', можно с уверенностью предположить, что обратный вызов' $ observ' будет вызван в '$ digest'. И обратный вызов '$ watch' также вызывается в' $ digest', но всякий раз, когда значение изменяется. Я думаю, что они выполняют ту же самую работу: «Посмотрите выражение, вызовите обратный вызов, измените значение». Разница в ключевых словах - это, возможно, просто синтаксический сахар, чтобы не смущать разработчика. –

+1

@fastreload, я полностью согласен с вашим комментарием .. Красиво написано! – PrimosK

+0

@fastreload ... Спасибо за замечательное объяснение. Если я правильно понял, Наблюдатели - это угловые выражения. Я прав? – Abilash

1

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

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

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

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

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

+2

Это довольно очевидно о его обычаях. Но почему был вопрос. Марк подвел итог красиво. – Abilash

+3

Я думаю, что параметры могут быть переключены - кажется, что они передают newValue, затем oldValue для attrs. $ Observ(). , , – blaster

Смежные вопросы