Sé que ambos Watchers
y Observers
se calculan tan pronto como algo $scope
cambia en AngularJS. Pero no podía entender cuál es exactamente la diferencia entre los dos.
Mi comprensión inicial es que Observers
se calculan para expresiones angulares que son condiciones en el lado HTML donde se Watchers
ejecutan cuando $scope.$watch()
se ejecuta la función. ¿Estoy pensando correctamente?
javascript
angularjs
Abilash
fuente
fuente
Respuestas:
$ observe () es un método en elobjeto Atributos y, como tal, solo se puede usar para observar / observar el cambio de valor de un atributo DOM. Solo se usa / llama dentro de las directivas. Use $ observe cuando necesite observar / mirar un atributo DOM que contiene interpolación (es decir, {{}} 's).
Por ejemplo,
attr1="Name: {{name}}"
y luego en una directiva:attrs.$observe('attr1', ...)
.(Si lo intentas
scope.$watch(attrs.attr1, ...)
no funcionará debido a los {{}} s, obtendrásundefined
). Usa $ watch para todo lo demás.$ watch () es más complicado. Puede observar / mirar una "expresión", donde la expresión puede ser una función o una cadena. Si la expresión es una cadena, es $ parse 'd (es decir, evaluada como una expresión angular ) en una función. (Es esta función la que se llama cada ciclo de resumen.) La expresión de cadena no puede contener {{}}. $ watch es un método en elobjeto Scope , por lo que se puede usar / invocar donde tenga acceso a un objeto Scope , por lo tanto, en
Debido a que las cadenas se evalúan como expresiones angulares, $ watch se usa a menudo cuando desea observar / mirar una propiedad de modelo / alcance. Por ejemplo,
attr1="myModel.some_prop"
luego en una función de controlador o enlace:scope.$watch('myModel.some_prop', ...)
oscope.$watch(attrs.attr1, ...)
(oscope.$watch(attrs['attr1'], ...)
).(Si lo intentas
attrs.$observe('attr1')
, obtendrás la cadenamyModel.some_prop
, que probablemente no sea lo que deseas).Como se discutió en los comentarios sobre la respuesta de @ PrimosK, todos los $ observa y los $ relojes se verifican en cada ciclo de resumen .
Las directivas con ámbitos aislados son más complicadas. Si se usa la sintaxis '@', puede $ observar o $ mirar un atributo DOM que contiene interpolación (es decir, {{}} 's). (La razón por la que funciona con $ watch es porque la sintaxis '@' hace la interpolación por nosotros, por lo tanto, $ watch ve una cadena sin {{}} 's.) Para que sea más fácil recordar cuál usar cuándo, sugiero usar $ observar para este caso también.
Para ayudar a probar todo esto, escribí un Plunker que define dos directivas. Uno (
d1
) no crea un nuevo alcance, el otro (d2
) crea un alcance aislado. Cada directiva tiene los mismos seis atributos. Cada atributo es tanto $ obser'd como $ watch'ed.Mire el registro de la consola para ver las diferencias entre $ observe y $ watch en la función de enlace. Luego haga clic en el enlace y vea qué $ observa y $ relojes son activados por los cambios de propiedad realizados por el controlador de clics.
Tenga en cuenta que cuando se ejecuta la función de enlace, los atributos que contienen {{}} aún no se evalúan (por lo tanto, si intenta examinar los atributos, obtendrá
undefined
). La única forma de ver los valores interpolados es usar $ observe (o $ watch si usa un alcance aislado con '@'). Por lo tanto, obtener los valores de estos atributos es una operación asincrónica . (Y es por eso que necesitamos las funciones $ observe y $ watch).A veces no necesitas $ observar o $ mirar. Por ejemplo, si el atributo contiene un número o un valor lógico (no una cadena), justo evaluar una vez:
attr1="22"
y, a continuación, digamos, en su función de vinculación:var count = scope.$eval(attrs.attr1)
. Si se trata solo de una cadena constante,attr1="my string"
simplemente utilícelaattrs.attr1
en su directiva (no necesita $ eval ())Vea también la publicación del grupo de Google de Vojta sobre las expresiones $ watch.
fuente
ng-src/ng-href
usar enattr.$observe
lugar descope.$watch
entonces?@
sintaxis. Creo que no hay diferencia de rendimiento (pero no he mirado el código fuente real).Si entiendo bien su pregunta, está preguntando cuál es la diferencia si registra la devolución de llamada del oyente
$watch
o si lo hace$observe
.La devolución de llamada registrada con
$watch
se dispara cuando$digest
se ejecuta.La devolución de llamada registrada con
$observe
se llama cuando el valor cambia de atributos que contienen interpolación (por ejemploattr="{{notJetInterpolated}}"
)Dentro de la directiva, puede usar ambos de manera muy similar:
o
fuente
$digest
fase, es seguro asumir que$observe
se llamará a la devolución de llamada$digest
. Y la$watch
devolución de llamada también se llamará,$digest
pero siempre que se cambie el valor. Creo que hacen exactamente el mismo trabajo: "ver la expresión, devolver la llamada, el valor cambia". La diferencia de palabras clave es posiblemente solo el azúcar sintáctico para no confundir al desarrollador.Creo que esto es bastante obvio:
Tenga en cuenta : tanto la función tiene dos argumentos,
function (oldValue, newValue)
He hecho un plunker, por lo que realmente puede comprender tanto su utilización. He usado la analogía de Chameleon para que sea más fácil de imaginar.
fuente
¿Por qué $ observe es diferente de $ watch?
WatchExpression se evalúa y se compara con el valor anterior de cada ciclo de digest (), si hay un cambio en el valor de watchExpression, se llama a la función watch.
$ observe es específico para observar valores interpolados. Si el valor de atributo de una directiva se interpola, por ejemplo
dir-attr="{{ scopeVar }}"
, la función de observación solo se llamará cuando se establezca el valor interpolado (y, por lo tanto, cuando $ digest ya haya determinado que se deben realizar actualizaciones). Básicamente ya hay un observador para la interpolación, y la función $ observe se complementa con eso.Vea $ observe & $ set en compile.js
fuente