Como é que uso mira de$.$ watch e $scope.candidatares-te a AngularJS?
não entendo como usar {[[0]} e $scope.$apply
. A documentação oficial não ajuda.
-
Estão ligados ao DOM?
Como posso atualizar DOM para o modelo?
Qual é o ponto de ligação entre eles?
eu tentei Este tutorial, mas é preciso a compreensão de $watch
e $apply
como garantido.
o que fazer $apply
e $watch
, e como usá-los apropriadamente?
7 answers
Ciclo de digestão e $scope
Em Primeiro Lugar, AngularJS define um conceito de um chamado ciclo de digestão . Este ciclo pode ser considerado como um ciclo, durante o qual AngularJS verifica se existem alterações a todas as variáveis assisti por todos os $scope
s. Então, se você tem $scope.myVar
definida no controlador e esta variável foi marcado para ser observado, em seguida, você estão implicitamente dizendo AngularJS para monitorar as mudanças em myVar
em cada iteração do laço.
$scope
, então rapidamente um loop digest levaria anos para avaliar e você iria rapidamente encontrar problemas de desempenho. É por isso que a equipe AngularJS nos deu duas maneiras de declarar algumas variáveis como sendo vigiadas (leia abaixo).
$ Watch ajuda a ouvir as mudanças $scope
Há duas maneiras de declarar uma variável como sendo observada.
- usando-o no seu modelo através da expressão
<span>{{myVar}}</span>
- adicionando-o manualmente através do serviço
$watch
Ad 1)
Este é o cenário mais comum e tenho certeza que você já viu isso antes, mas você não sabia que isso criou um relógio no fundo. Sim, tinha! Utilizando directivas AngularJS (tais como ng-repeat
) pode também criar relógios implícitos.
Ad 2)
É assim que cria os seus próprios relógios. $watch
o serviço ajuda-o a executar algum código quando algum valor ligado ao $scope
mudou. É raramente usado, mas às vezes é útil. Por exemplo, se você quiser executar algum código cada vez que 'myVar' muda, você pode fazer o seguinte:
function MyController($scope) {
$scope.myVar = 1;
$scope.$watch('myVar', function() {
alert('hey, myVar has changed!');
});
$scope.buttonClicked = function() {
$scope.myVar = 2; // This will trigger $watch expression to kick in
};
}
$aplicar permite integrar as alterações com o ciclo do digest
Podes pensar no $apply
função de integração mecanismo . Cada vez que mudas uma variável vigiada ligada ao $scope
object directly, AngularJS will know that the change has happened. Isso é porque AngularJS já sabia para monitorar essas mudanças. Assim, se isso acontecer em código gerenciado pelo framework, o ciclo digest continuará.
No entanto, às vezes você quer mudar algum valor fora do mundo AngularJS e ver as mudanças propagarem-se normalmente.
Considere isto-você tem um $scope.myVar
valor que será modificado no manipulador de um jQuery $.ajax()
. Isto irá acontecer em algum momento no futuro. AngularJS não pode esperar que isso aconteça, uma vez que não foi instruído a esperar por jQuery.
Para resolver este problema, $apply
foi introduzido. Permite iniciar o ciclo de digestão explicitamente. No entanto, você só deve usar isso para migrar alguns dados para AngularJS( integração com outros frameworks), mas nunca usar este método combinado com o código AngularJS regular, como AngularJS irá jogar um erro, então.
Bem, você realmente deve seguir o tutorial novamente, agora que você sabe tudo isso. O ciclo de digestão certificar-se-á de que o UI e o código JavaScript permanecem sincronizados, avaliando cada observador ligado a todos os $scope
desde que nada mude. Se não ocorrerem mais mudanças no loop digest, então é considerado terminado.
Você pode anexar objectos ao objecto $scope
explicitamente no Controller, or by declaring them in {{expression}}
form directly in the view.
Em AngularJS, actualizamos os nossos modelos, e as nossas vistas/modelos actualizam o DOM "automaticamente" (através de directivas incorporadas ou personalizadas).
$ Apply and $watch, both being Scope methods, are not related to the DOM.A página de conceitos (secção "tempo de execução") tem uma boa explicação para o ciclo $digest, $apply, a fila $evalAsync e a lista $watch. Aqui está a imagem que acompanha o texto:
Qualquer código que tenha acesso a um âmbito de Aplicação – normalmente os controladores e as diretivas (suas funções de ligação e/ou seus controladores) – podem configurar uma "expressão de vigilância" que AngularJS avaliará em função desse escopo. Esta avaliação acontece sempre que AngularJS entra em seu ciclo $digest (em particular, o ciclo "$watch list"). Você pode observar propriedades individuais de escopo, você pode definir uma função para assistir duas propriedades juntas, você pode assistir o comprimento de uma matriz, etc.Quando as coisas acontecem "dentro de AngularJS" – por exemplo, você digita em uma caixa de texto que tem AngularJS databinding de duas vias ativado (ou seja, usa ng-model), um $http callback incêndios, etc. - a aplicação $já foi chamada, por isso estamos dentro do rectângulo "AngularJS" na figura acima. Todas as expressões de vigilância serão avaliadas (possivelmente mais de uma vez – até que não sejam detectadas mais alterações).
Quando as coisas acontecem "fora de AngularJS" - por exemplo, você usou o bind() em uma diretiva e então esse evento dispara, resultando em seu callback ser chamado, ou algum jQuery incêndios registados, ainda estamos no rectângulo "nativo". Se o código de retorno modificar qualquer coisa que qualquer relógio $está assistindo, ligue $aplicar para entrar no retângulo AngularJS, fazendo com que o loop $digest para correr, e, portanto, AngularJS vai notar a mudança e fazer sua magia.Este blog foi coberto por tudo o que cria exemplos e explicações compreensíveis.
As funções AngularJS $scope
$watch(), $digest()
e $apply()
são algumas das funções centrais em AngularJS. Compreensão $watch()
, $digest()
e {[9] } é essencial para entender AngularJS.
Quando você cria uma ligação de dados de algum lugar na sua visão para uma variável no objeto $ scope, AngularJS cria um" relógio " internamente. Um relógio significa que os relógios AngularJS mudam na variável em $scope object
. O framework está "observando" a variável. Os relógios são criados usando a função $scope.$watch()
que irei cobrir mais tarde neste texto.
Nos pontos-chave da sua aplicação, O AngularJS chama a função $scope.$digest()
. Esta função itera através de todos os relógios e verificações se alguma das variáveis observadas mudou. Se uma variável observada mudou, uma função correspondente de ouvinte é chamada. A função ouvinte faz qualquer trabalho que precisa fazer, por exemplo alterar um texto HTML para refletir o novo valor da variável observada. Assim, a função $digest()
é o que despoleta a ligação de dados para atualizar.
$scope.$digest()
functions for you, but in some situations you may have to call them yourself. Portanto, é realmente bom saber como eles funcionam.
A função $scope.$apply()
é usada para executar algum código, e depois ligar $scope.$digest()
depois disso, para que todos os relógios sejam verificados e o correspondente as funções de ouvinte de Vigia são chamadas. A função $apply()
é útil ao integrar AngularJS com outro código.
Vou entrar em mais detalhes sobre as funções $watch(), $digest()
e $apply()
no resto deste texto.
$watch ()
A função $scope.watch()
cria um relógio de alguma variável. Quando regista um relógio, passa duas funções como parâmetros para a função $watch()
:
- uma função de valor
- uma função ouvinte
$scope.$watch(function() {},
function() {}
);
A primeira função é a função valor e a segunda função é a função ouvinte.
A função valor deve devolver o valor que está a ser observado. AngularJS pode então verificar o valor devolvido com o valor que a função de relógio devolveu da última vez. Dessa forma AngularJS pode determinar se o valor mudou. Aqui está um exemplo:
$scope.$watch(function(scope) { return scope.data.myVar },
function() {}
);
Este exemplo a função valule devolve a variável $scope
scope.data.myVar
. Se o valor deste mudanças variáveis, um valor diferente será devolvido, e AngularJS vai chamar a função ouvinte.
Observe como a função valor toma o escopo como parâmetro (sem o $ no nome). Através deste parâmetro a função valor pode acessar o $scope
e suas variáveis. A função valor também pode observar variáveis globais em vez disso, se você precisar disso,mas na maioria das vezes você vai assistir a uma variável $scope
.
A função ouvinte deve fazer o que for necessário se o valor tiver alteracao. Talvez você precise mudar o conteúdo de outra variável, ou definir o conteúdo de um elemento HTML ou algo assim. Aqui está um exemplo:
$scope.$watch(function(scope) { return scope.data.myVar },
function(newValue, oldValue) {
document.getElementById("").innerHTML =
"" + newValue + "";
}
);
Este exemplo define o HTML interno de um elemento HTML para o novo valor da variável, incorporado no elemento b que faz o valor negrito. Claro que você poderia ter feito isso usando o código {{ data.myVar }
, mas este é apenas um exemplo do que você pode fazer dentro da função ouvinte.
A função $scope.$digest()
itera através de todos os relógios do $scope object
, e seus objetos de escopo $criança (se tiver algum). Quando $digest()
itera sobre os relógios, ele chama a função de valor para cada relógio. Se o valor retornado pela função valor é diferente do valor retornado da última vez que foi chamado, a função ouvinte para esse relógio é chamada.
A função $digest()
é chamada sempre que AngularJS pensa que é necessário. Por exemplo, após a execução de um manipulador de botão AJAX
os resultados das chamadas (após a função 'callback' feita() / fail() ter sido executada).
Você pode encontrar alguns casos de canto onde AngularJS não chama a função $digest()
para você. Você Geralmente vai detectar isso ao notar que as ligações de dados não atualizam os valores apresentados. Nesse caso, Liga-me e deve funcionar. Ou, você pode talvez usar $scope.$apply()
em vez disso, o que eu vou explicar na próxima seção.
$aplicar ()
A função $scope.$apply()
assume uma função como parâmetro que é executado, e depois disso $scope.$digest()
é chamado internamente. Isso torna mais fácil para você se certificar de que todos os relógios são verificados, e, portanto, todas as combinações de dados atualizados. Aqui está um exemplo $apply()
:
$scope.$apply(function() {
$scope.data.myVar = "Another value";
});
A função passada para a função $apply()
como parâmetro irá alterar o valor de $scope.data.myVar
. Quando a função Sair AngularJS irá chamar a função $scope.$digest()
para que todas as vigias sejam verificadas quanto a alterações nos valores observados.
Exemplo
Para ilustrar como$watch()
, $digest(
) e $apply()
funciona, Veja este exemplo:
<div ng-controller="myController">
{{data.time}}
<br/>
<button ng-click="updateTime()">update time - ng-click</button>
<button id="updateTimeButton" >update time</button>
</div>
<script>
var module = angular.module("myapp", []);
var myController1 = module.controller("myController", function($scope) {
$scope.data = { time : new Date() };
$scope.updateTime = function() {
$scope.data.time = new Date();
}
document.getElementById("updateTimeButton")
.addEventListener('click', function() {
console.log("update time clicked");
$scope.data.time = new Date();
});
});
</script>
O Seu exemplo liga a variável $scope.data.time
a uma directiva de interpolação que funde o valor variável na página HTML. Esta ligação cria um relógio internamente no $scope.data.time variable
.
O exemplo também contém dois botões. O primeiro botão tem um ng-click
ouvinte ligado a ele. Quando esse botão é clicado a função $scope.updateTime()
é chamada, e depois que AngularJS chama $scope.$digest()
de modo que as ligações de dados são actualizacao.
O segundo botão recebe um ouvinte de eventos JavaScript padrão ligado a ele de dentro da função de controle. Quando o segundo botão é clicado essa função ouvinte é executada. Como você pode ver, as funções de ouvinte para ambos os botões fazem quase o mesmo, mas quando a função de ouvinte do segundo botão é chamada, a ligação de dados não é atualizada. Isso é porque o $scope.$digest()
não é chamado depois que o ouvinte de eventos do segundo botão é executado. Assim, se você clicar no segundo botão a hora é actualizada na variável $scope.data.time
, mas a hora Nova nunca é mostrada.
Para corrigir isso podemos adicionar uma chamada $scope.$digest()
para a última linha do ouvinte de Eventos Botão, assim:
document.getElementById("updateTimeButton")
.addEventListener('click', function() {
console.log("update time clicked");
$scope.data.time = new Date();
$scope.$digest();
});
Em vez de chamar $digest()
dentro da função de ouvinte de botões, também podia ter usado a função $apply()
assim:
document.getElementById("updateTimeButton")
.addEventListener('click', function() {
$scope.$apply(function() {
console.log("update time clicked");
$scope.data.time = new Date();
});
});
Observe como a função $scope.$apply()
é chamada de dentro do ouvinte de eventos do botão, e como a atualização da variável $scope.data.time
é realizada dentro a função passou como parâmetro para a função $apply()
. Quando a chamada de função $apply()
termina as chamadas AngularJS $digest()
internamente, então todas as ligações de dados são atualizadas.
AngularJS estende isto events-loop , criando algo chamado AngularJS context
.
$vigia()
Cada vez que amarras algo na UI inseres um $watch
numa lista$watch
.
User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />
Aqui temos $scope.user
, que está ligado à primeira entrada, e temos {7}, que está ligado à segunda. Fazendo isso, adicionamos dois $watch
es to the $watch
list .
Quando o nosso modelofor carregado, ou seja, na fase de ligação, o compilador procurará cada directiva e criará todos os $watch
es que são necessários.
AngularJS fornece $watch
, $watchcollection
e $watch(true)
. Abaixo está um diagrama limpo que explica todos os três retirados de observadores em profundidade .
angular.module('MY_APP', []).controller('MyCtrl', MyCtrl)
function MyCtrl($scope,$timeout) {
$scope.users = [{"name": "vinoth"},{"name":"yusuf"},{"name":"rajini"}];
$scope.$watch("users", function() {
console.log("**** reference checkers $watch ****")
});
$scope.$watchCollection("users", function() {
console.log("**** Collection checkers $watchCollection ****")
});
$scope.$watch("users", function() {
console.log("**** equality checkers with $watch(true) ****")
}, true);
$timeout(function(){
console.log("Triggers All ")
$scope.users = [];
$scope.$digest();
console.log("Triggers $watchCollection and $watch(true)")
$scope.users.push({ name: 'Thalaivar'});
$scope.$digest();
console.log("Triggers $watch(true)")
$scope.users[0].name = 'Superstar';
$scope.$digest();
});
}
$digest
loop
Quando o navegador recebe um evento que pode ser gerido pelo contexto AngularJS, o laço $digest
será disparado. Este ciclo é feito de dois loops menores. Um processa a fila $evalAsync
e o outro processa a $watch list
. O $digest
vai percorrer a lista de $watch
que temos
app.controller('MainCtrl', function() {
$scope.name = "vinoth";
$scope.changeFoo = function() {
$scope.name = "Thalaivar";
}
});
{{ name }}
<button ng-click="changeFoo()">Change the name</button>
Aqui só temos um porque o ng-click não cria relógios.
Carregamos no botão.
- o navegador recebe um evento que irá entrar no contexto AngularJS
- o ciclo
$digest
vai correr e vai pedir a cada $watch para alterações.
Desde o ... alterações em $scope.name
relata uma mudança, que forçará outro laço - O importante aqui é que cada evento que entrar no contexto AngularJS irá executar um laço
$digest
. Isso significa que toda vez que escrevermos uma letra em uma entrada, o loop vai correr verificando cada$watch
neste pagina.
$digest
.
O novo loop não diz nada.
O navegador recupera o controlo e actualiza o DOM.
reflectindo o novo valor de $scope.name
$aplicar ()
Se você ligar $apply
quando um evento é disparado, ele vai passar pelo contexto angular, mas se você não chamá-lo, ele vai correr para fora dele. É tão fácil como isso. $apply
chamarei o $digest()
loop internamente e iterate sobre todos os relógios para garantir que o DOM é atualizado com o novo valor atualizado.
O método $apply()
despoletará observadores em toda a cadeia $scope
enquanto que o método $digest()
só despoletará observadores na cadeia atual $scope
e sua children
. quando nenhum dos objectos superiores $scope
necessita de saber sobre as alterações locais, pode usar $digest()
.
Também há $watchGroup
e $watchCollection
. Especificamente, $watchGroup
é realmente útil se você quiser chamar uma função para atualizar um objeto que tem várias propriedades em uma vista que não é objeto dom, por exemplo, outra vista em canvas, webGL ou pedido de servidor. Aqui, a documentação link .
$watch
, $apply
, $digest
e digerir ciclos em:
AngularJS-Watcher Understanding, $ watch, $watchGroup, $watchCollection, ng-change
AngularJS-Understanding digest cycle (digest phase or digest process or digest loop or digest loop)
tutorial AngularJS-Understanding $apply and $digest (in profundidade)
A seguir estão alguns slides usados nesses vídeos para explicar os conceitos (apenas em caso, se os links acima são removidos/não funcionando).
Na imagem acima, " $ scope.c" não está sendo vigiado como não é usado em nenhuma das ligações de dados (em marcação). Os outros dois ($scope.a
e $scope.b
) serão vigiados.
A partir da imagem acima: com base no respectivo evento do navegador, AngularJS captura o evento, executa o ciclo de digestão (passa por todas as vigias para mudanças), executa funções de vigia e atualiza o DOM. Se não forem eventos de navegação, o ciclo de digest pode ser activado manualmente usando $apply
ou $digest
.
Mais sobre $apply
e $digest
:
Acaba de ler tudo o que está acima, aborrecido e sonolento (desculpa, mas é verdade). Muito técnico, profundo, detalhado e seco. Porque estou a escrever? Como AngularJS é massivo, muitos conceitos interligados podem enlouquecer qualquer um. Pergunto-me muitas vezes se não sou inteligente o suficiente para as compreender. Não! É porque tão poucos podem explicar a tecnologia numa língua para dummie com todas as terminologias! Está bem, Deixa-me tentar.
1) são tudo coisas motivadas pelo evento.(I hear a gargalhada, mas continua a ler.
Se não sabes o que é um evento
acho que colocas um botão
na página, ligue-a w / a função usando "on-click", esperando por
usuários para clicar nele para desencadear as ações que você planta dentro do
funcao. Ou pense no "gatilho" do servidor SQL / Oracle.
2) $o relógio é "on-click".
O que é especial sobre ele é que ele tem 2 funções como parâmetros, o primeiro dá o valor do evento, o segundo leva o valor para consideracao...
3) $digest é o chefe que procura incansavelmente., bla-bla-bla, mas um bom chefe.
4) $Aplicar dá - Lhe a forma como deseja fazê-lo manualmente, Como se fosse à prova de falhas (no caso de o botão "on-click" não fazer efeito, obriga-o a correr.)
Agora, vamos torná-lo visual. Imagine isso para torná-lo ainda mais fácil de pegar a idéia:
Num restaurante,
- Empregados de mesa é suposto receber ordens dos clientes, isto é ...
$watch(
function(){return orders;},
function(){Kitchen make it;}
);
- O gerente anda por aí para ter a certeza que todos os empregados estão acordados, a responder a qualquer sinal de alterações dos clientes. Isto é ... $digest()
- O dono tem o poder máximo de conduzir toda a gente a pedido, isto é ... $apply()