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.

O que não entendo especificamente:
    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?

Author: Peter Mortensen, 2013-02-27

7 answers

Tens de estar ciente de como O AngularJS funciona para o entenderes.

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 $scopes. 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.

Uma pergunta natural de seguimento seria: está tudo ligado a ser vigiado? Felizmente, não. Se você observasse as mudanças em cada objeto em seu $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.
  1. usando-o no seu modelo através da expressão <span>{{myVar}}</span>
  2. 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.

Como é que tudo isto está relacionado com o DOM?

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 $scopedesde 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.

Espero que isso ajude a esclarecer alguns conhecimentos básicos sobre tudo isto. Mais leituras:
 1661
Author: ŁukaszBachman, 2017-09-19 11:47:30

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:

$digest loop

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.
 152
Author: Mark Rajcok, 2016-02-02 08:17:08

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.

A maior parte das vezes, os AngularJS chamam-lhe $scope.$watch() and $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
Aqui está um exemplo:
$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.

$Digest ()

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.

 56
Author: Alex Jolig, 2016-02-22 10:13:37

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 $watches 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 $watches 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 .

Enter image description here

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();
  });
}

Http://jsfiddle.net/2Lyn0Lkb/

$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.
  1. o navegador recebe um evento que irá entrar no contexto AngularJS
  2. o ciclo $digest vai correr e vai pedir a cada $watch para alterações.
  3. Desde o ... alterações em $scope.name relata uma mudança, que forçará outro laço $digest. O novo loop não diz nada. O navegador recupera o controlo e actualiza o DOM. reflectindo o novo valor de $scope.name
  4. 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.

$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().

 37
Author: Thalaivar, 2017-01-07 15:14:54

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 .

 17
Author: Utkarsh Bhardwaj, 2015-04-08 05:29:37
Encontrei vídeos muito profundos que cobriam $watch, $apply, $digest e digerir ciclos em:

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).

Enter image description here

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.

Enter image description here

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:

Enter image description here

 15
Author: user203687, 2017-01-07 15:08:25

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()

 10
Author: Jeb50, 2017-02-07 01:20:51