Eu sei que ambos Watchers
e Observers
são computados assim que algo $scope
muda no AngularJS. Mas não conseguia entender qual é exatamente a diferença entre os dois.
Meu entendimento inicial é que Observers
são calculados para expressões angulares que são condições no lado HTML, onde Watchers
executadas quando a $scope.$watch()
função é executada. Estou pensando corretamente?
javascript
angularjs
Abilash
fonte
fonte
Respostas:
$ observe () é um método noobjeto Atributos e, como tal, só pode ser usado para observar / observar a alteração de valor de um atributo DOM. Só é usado / chamado dentro de diretivas. Use $ observe quando precisar observar / observar um atributo DOM que contenha interpolação (ou seja, {{}} ').
Por exemplo,
attr1="Name: {{name}}"
e depois numa directiva:attrs.$observe('attr1', ...)
.(Se você tentar
scope.$watch(attrs.attr1, ...)
, não funcionará por causa dos {{}} s - você receberáundefined
.) Use $ watch para todo o resto.$ watch () é mais complicado. Ele pode observar / observar uma "expressão", onde a expressão pode ser uma função ou uma string. Se a expressão for uma string, é $ parse 'd (isto é, avaliado como uma expressão Angular ) em uma função. (É essa função que é chamada todo ciclo de digestão.) A expressão da string não pode conter {{}} 's. $ watch é um método noobjeto Scope , portanto, pode ser usado / chamado sempre que você tiver acesso a um objeto de escopo, portanto, em
Como as seqüências de caracteres são avaliadas como expressões angulares, $ watch geralmente é usado quando você deseja observar / observar uma propriedade de modelo / escopo. Por exemplo,
attr1="myModel.some_prop"
em uma função de controlador ou link:scope.$watch('myModel.some_prop', ...)
ouscope.$watch(attrs.attr1, ...)
(ouscope.$watch(attrs['attr1'], ...)
).(Se você tentar,
attrs.$observe('attr1')
obterá a stringmyModel.some_prop
, o que provavelmente não é o que você deseja.)Conforme discutido nos comentários da resposta do @ PrimosK, todos os $ observes e $ watches são verificados a cada ciclo de digestão .
Diretivas com escopos isolados são mais complicadas. Se a sintaxe '@' for usada, você pode $ observar ou $ assistir um atributo DOM que contenha interpolação (ou seja, {{}} '). (O motivo pelo qual ele trabalha com $ watch é porque a sintaxe '@' faz a interpolação para nós, portanto, $ watch vê uma string sem {{}} '.) Para facilitar a lembrança de qual usar, sugiro usar $ observe também para este caso.
Para ajudar a testar tudo isso, escrevi um Plunker que define duas diretivas. Um (
d1
) não cria um novo escopo, o outro (d2
) cria um escopo isolado. Cada diretiva tem os mesmos seis atributos. Cada atributo é $ observe'd e $ watch'ed.Veja o log do console para ver as diferenças entre $ observe e $ watch na função de vinculação. Em seguida, clique no link e veja quais $ observa e $ relógios são acionados pelas alterações de propriedade feitas pelo manipulador de cliques.
Observe que quando a função de link é executada, quaisquer atributos que contenham {{}} ainda não são avaliados (portanto, se você tentar examinar os atributos, obterá
undefined
). A única maneira de ver os valores interpolados é usar $ observe (ou $ watch se estiver usando um escopo isolado com '@'). Portanto, obter os valores desses atributos é uma operação assíncrona . (E é por isso que precisamos das funções $ observe e $ watch.)Às vezes você não precisa de $ observe ou $ watch. Por exemplo, se o seu atributo contém um número ou um booleano (não uma string), apenas avaliá-lo uma vez:
attr1="22"
e, em seguida, digamos, a sua função que relaciona:var count = scope.$eval(attrs.attr1)
. Se for apenas uma string constante -attr1="my string"
- apenas useattrs.attr1
na sua diretiva (não é necessário $ eval ()).Veja também o post do grupo do Google sobre Vojta sobre expressões $ watch.
fonte
ng-src/ng-href
usar emattr.$observe
vezscope.$watch
disso?@
sintaxe. Eu acredito que não há diferença de desempenho (mas eu não olhei o código fonte real).Se entendi bem sua pergunta, você está perguntando qual é a diferença se registrar o retorno de chamada do ouvinte
$watch
ou se o fizer$observe
.O retorno de chamada registerd com
$watch
é acionado quando$digest
é executado.O retorno de
$observe
chamada registrado com é chamado quando alterações de valor de atributos que contêm interpolação (por exemploattr="{{notJetInterpolated}}"
).Diretiva interna, você pode usar os dois de maneira muito semelhante:
ou
fonte
$digest
fase, é seguro assumir que o$observe
retorno de chamada será chamado$digest
. E o$watch
retorno de chamada também será chamado,$digest
mas sempre que o valor for alterado. Eu acho que eles fazem exatamente o mesmo trabalho: "observe a expressão, ligue para retorno de chamada, o valor muda". A diferença da palavra-chave é possivelmente apenas açúcar sintático para não confundir o desenvolvedor.Eu acho que isso é bastante óbvio:
Lembre-se : a função possui dois argumentos,
function (oldValue, newValue)
Eu fiz um plunker, para que você possa realmente entender sobre a utilização deles. Eu usei a analogia do Chameleon para facilitar a imagem.
fonte
Por que $ observe é diferente de $ watch?
A watchExpression é avaliada e comparada com o valor anterior a cada ciclo digest (). Se houver uma alteração no valor watchExpression, a função watch será chamada.
$ observe é específico para observar valores interpolados. Se o valor do atributo de uma diretiva for interpolado, por exemplo
dir-attr="{{ scopeVar }}"
, a função de observação será chamada apenas quando o valor interpolado estiver definido (e, portanto, quando $ digest já determinar que é necessário fazer atualizações). Basicamente, já existe um observador para a interpolação, e a função $ observe pega isso.Veja $ observe e $ set em compile.js
fonte