Angular JS: Qual é a necessidade da function de link da diretiva quando já temos o controlador da diretiva com o escopo?

Eu preciso executar algumas operações no escopo e no modelo. Parece que eu posso fazer isso na function de link ou na function de controller (já que ambos têm access ao escopo).

Quando é o caso quando eu tenho que usar a function de link e não o controlador?

 angular.module('myApp').directive('abc', function($timeout) { return { restrict: 'EA', replace: true, transclude: true, scope: true, link: function(scope, elem, attr) { /* link function */ }, controller: function($scope, $element) { /* controller function */ } }; } 

Além disso, entendo que o link é o mundo não angular. Então, posso usar $watch , $digest e $apply .

Qual é o significado da function de link , quando já tínhamos controlador?

Depois da minha luta inicial com as funções de link e controller e lendo bastante sobre eles, acho que agora tenho a resposta.

Primeiro vamos entender

Como as diretivas angulares funcionam em poucas palavras:

  • Começamos com um modelo (como uma string ou carregado em uma string)

    var templateString = '

    {{5 + 10}}

    ';

  • Agora, este templateString é empacotado como um elemento angular

    var el = angular.element(templateString);

  • Com el , agora compilamos com $compile para recuperar a function de link .

    var l = $compile(el)

    Aqui é o que acontece,

    • $compile percorre todo o modelo e coleta todas as diretivas que ele reconhece.
    • Todas as diretivas descobertas são compiladas recursivamente e suas funções de link são coletadas.
    • Em seguida, todas as funções de link são agrupadas em uma nova function de link e retornadas como l .
  • Finalmente, nós fornecemos function de scope para esta function l (link) que executa ainda mais as funções de link encapsulado com este scope e seus elementos correspondentes.

    l(scope)

  • Isso adiciona o template como um novo nó ao DOM e chama o controller que adiciona seus relógios ao escopo que é compartilhado com o modelo no DOM.

insira a descrição da imagem aqui

Comparando compile vs link vs controller :

  • Cada diretiva é compilada apenas uma vez e a function de link é retida para reutilização. Portanto, se houver algo aplicável a todas as instâncias de uma diretiva, ela deverá ser executada dentro da function de compile da diretiva.

  • Agora, após a compilation, temos a function link que é executada ao append o modelo ao DOM . Portanto, nós executamos tudo o que é específico para cada instância da diretiva. Por exemplo: anexando events , alterando o modelo com base no escopo , etc.

  • Finalmente, o controlador deve estar disponível para ser dynamic e reativo, enquanto a diretiva funciona no DOM (depois de conectado). Assim sendo:

    (1) Depois de configurar a visualização [ V ] (ou seja, modelo) com link. $scope é nosso [ M ] e $controller é nosso [ C ] em MVC

    (2) Aproveite a binding bidirecional com o $ scope configurando relógios.

    (3) Espera-se que sejam adicionados controles de $scope no controlador, já que é isso que está assistindo o modelo durante o tempo de execução.

    (4) Por fim, o controller também é usado para poder se comunicar entre diretivas relacionadas. (Como o exemplo myTabs em https://docs.angularjs.org/guide/directive )

    (5) É verdade que poderíamos ter feito tudo isso na function de link , mas também na separação de interesses .

Portanto, finalmente, temos o seguinte que se encheckbox perfeitamente todas as peças:

insira a descrição da imagem aqui

Por que os controladores são necessários?

A diferença entre o link e o controller entra em ação quando você deseja aninhar diretivas em seu DOM e expor as funções da API da diretiva pai para as aninhadas.

Dos docs :

Melhor prática: use o controlador quando quiser expor uma API a outras diretivas. Caso contrário, use o link.

Digamos que você queira ter duas diretivas, my-form e my-text-input e você deseja que a diretiva my-text-input apareça apenas dentro do my-form e em nenhum outro lugar.

Nesse caso, você dirá ao definir a diretiva my-text-input que requer um controlador do elemento DOM parent usando o argumento require , da seguinte forma: require: '^myForm' . Agora, o controlador do elemento pai será injected na function de link como o quarto argumento, seguindo $scope, element, attributes . Você pode chamar funções nesse controlador e se comunicar com a diretiva pai.

Além disso, se tal controlador não for encontrado, um erro será levantado.

Por que usar link em tudo

Não há necessidade real de usar a function de link se estiver definindo o controller pois o $scope está disponível no controller . Além disso, ao definir link e controller , é necessário ter cuidado com a ordem de invocação dos dois (o controller é executado antes).

No entanto, de acordo com a maneira angular , a maioria das manipulações de DOM e bidirecionais usando $watchers geralmente é feita na function de link , enquanto a API para crianças e manipulação de $scope é feita no controller . Esta não é uma regra difícil e rápida, mas isso tornará o código mais modular e ajudará na separação de interesses (o controlador manterá o estado da directive e a function de link manterá as ligações externas do DOM +).

A function / object controller representa um MVC (abstraction model-view-controller). Embora não haja nada de novo para escrever sobre o MVC, ele ainda é o mais significativo avanço angular: dividir as preocupações em partes menores. E é isso, nada mais, por isso, se você precisar reagir às mudanças no Model que vêm do View the Controller é a pessoa certa para fazer esse trabalho.

A história sobre a function de link é diferente, está vindo de uma perspectiva diferente, em seguida, MVC. E é realmente essencial, uma vez que queremos cruzar os limites de um controller/model/view (template) .

Vamos começar com os parâmetros que são passados ​​para a function de link :

 function link(scope, element, attrs) { 
  • escopo é um object de escopo angular.
  • elemento é o elemento jqLite que essa diretiva corresponde.
  • attrs é um object com os nomes de atributos normalizados e seus valores correspondentes.

Para colocar o link no contexto, devemos mencionar que todas as diretivas estão passando por estas etapas do processo de boot: Compile , Link . Um extrato do livro de Brad Green e Shyam Seshadri Angular JS :

Fase de compilation (uma irmã do link, vamos mencionar aqui para obter uma imagem clara):

Nesta fase, Angular percorre o DOM para identificar todas as diretivas registradas no modelo. Para cada diretiva, ela transforma o DOM com base nas regras da diretiva (modelo, replace, transclude e assim por diante) e chama a function de compilation, se existir. O resultado é uma function de modelo compilada,

Fase de binding :

Para tornar a exibição dinâmica, o Angular executa uma function de link para cada diretiva. As funções de link normalmente criam listeners no DOM ou no modelo. Esses ouvintes mantêm a exibição e o modelo em sincronia o tempo todo.

Um bom exemplo de como usar o link pode ser encontrado aqui: Criando diretivas personalizadas . Veja o exemplo: Criando uma diretiva que manipula o DOM , que insere um “data-hora” na página, atualizada a cada segundo.

Apenas um trecho muito curto daquela fonte rica acima, mostrando a manipulação real com o DOM. Há function hooked para o serviço $ timeout, e também é apagado em sua chamada de destruidor para evitar vazamentos de memory

 .directive('myCurrentTime', function($timeout, dateFilter) { function link(scope, element, attrs) { ... // the not MVC job must be done function updateTime() { element.text(dateFilter(new Date(), format)); // here we are manipulating the DOM } function scheduleUpdate() { // save the timeoutId for canceling timeoutId = $timeout(function() { updateTime(); // update DOM scheduleUpdate(); // schedule the next update }, 1000); } element.on('$destroy', function() { $timeout.cancel(timeoutId); }); ...