Tutorial AngularJS: Desmistificando Diretivas Personalizadas

Publicados: 2022-03-11

Com o rápido crescimento do JavaScript como uma linguagem de pilha completa, mais e mais aplicativos estão utilizando estruturas que permitem que o navegador da Web lide com mais processamento da interface do usuário, como vinculação de dados, gerenciamento de visualizações de dados, transformação de dados e muitos outros serviços. Um dos frameworks mais capazes, extensíveis e populares é o AngularJS, e um dos componentes mais úteis do framework AngularJS é algo chamado diretiva . AngularJS fornece muitas diretivas úteis e, ainda mais importante, fornece uma estrutura rica para criar diretivas personalizadas.

O que é uma diretiva? Simplificando, diretivas são funções JavaScript que manipulam e adicionam comportamentos a elementos HTML DOM. As diretivas podem ser muito simplistas ou extremamente complicadas. Portanto, obter uma compreensão sólida de suas muitas opções e funções que os manipulam é fundamental.

Neste tutorial, as quatro funções que executam como uma diretiva são criadas e aplicadas ao DOM serão exploradas e exemplos serão fornecidos. Este post pressupõe alguma familiaridade com AngularJS e diretivas personalizadas. Se você é novo no Angular, pode gostar de um tutorial sobre como criar seu primeiro aplicativo AngularJS.

As quatro funções do ciclo de vida da diretiva AngularJS

Existem muitas opções que podem ser configuradas e como essas opções estão relacionadas entre si é importante. Cada diretiva passa por algo semelhante a um ciclo de vida à medida que o AngularJS compila e vincula o DOM. O ciclo de vida da diretiva começa e termina no processo de inicialização do AngularJS, antes que a página seja renderizada. No ciclo de vida de uma diretiva, existem quatro funções distintas que podem ser executadas se forem definidas. Cada um permite que o desenvolvedor controle e personalize a diretiva em diferentes pontos do ciclo de vida.

As quatro funções são: compile , controller , pre-link e post-link .

A função compile permite que a diretiva manipule o DOM antes de ser compilado e vinculado, permitindo adicionar/remover/alterar diretivas, bem como adicionar/remover/alterar outros elementos DOM.

A função do controlador facilita a comunicação diretiva. As diretivas de irmãos e filhos podem solicitar que o controlador de seus irmãos e pais comunique informações.

A função de pré-link permite a manipulação privada de $scope antes do início do processo de pós-link.

O método post-link é o principal método de trabalho da diretiva.

Na diretiva, a manipulação do DOM pós-compilação ocorre, os manipuladores de eventos são configurados, assim como os relógios e outras coisas. Na declaração da diretiva, as quatro funções são definidas assim.

 .directive("directiveName",function () { return { controller: function() { // controller code here... }, compile: { // compile code here... return { pre: function() { // pre-link code here... }, post: function() { // post-link code here... } }; } } })

Normalmente, nem todas as funções são necessárias. Na maioria das circunstâncias, os desenvolvedores simplesmente criarão um controlador e uma função de pós-link seguindo o padrão abaixo.

 .directive("directiveName",function () { return { controller: function() { // controller code here... }, link: function() { // post-link code here... } } })

Nesta configuração, link refere-se à função post-link .

Se todas ou algumas das funções são definidas, sua ordem de execução é importante, especialmente sua execução em relação ao restante do aplicativo AngularJS.

Execução da função da diretiva AngularJS em relação a outras diretivas

Considere o seguinte trecho de HTML com as diretivas parentDir , childDir e grandChildDir aplicadas ao fragmento HTML.

 <div parentDir> <div childDir> <div grandChildDir> </div> </div> </div>

A ordem de execução das funções dentro de uma diretiva e em relação a outras diretivas é a seguinte:

  • Fase de compilação
    • Função de compilação : parentDir
    • Função de compilação : childDir
    • Função de compilação : grandChildDir
  • Controlador e Fase Pré-Link
    • Função do controlador : parentDir
    • Função de pré-link : parentDir
    • Função do controlador : childDir
    • Função de pré-link : childDir
    • Função do controlador : grandChildDir
    • Função de pré-link : grandChildDir
  • Fase Pós-Link
    • Função pós-link : grandChildDir
    • Função pós-link : childDir
    • Função pós-link : parentDir

O tutorial da função diretiva AngularJS - ordem de execução relativa a outras diretivas.

Explicação da Função da Diretiva AngularJS: Mergulho Profundo

A fase de compilação ocorre primeiro. Essencialmente, a fase de compilação anexa ouvintes de eventos aos elementos DOM. Por exemplo, se um determinado elemento DOM estiver vinculado a uma propriedade $scope , o ouvinte de eventos que permite que ele seja atualizado com o valor da propriedade $scope é aplicado ao elemento DOM. O processo de compilação começa com o elemento DOM raiz do qual o aplicativo AngularJS foi inicializado e percorre as ramificações do DOM usando uma travessia em profundidade, compilando primeiro um pai e depois seus filhos até os nós folha.

Uma vez que a compilação esteja completa, as diretivas não podem mais ser adicionadas ou removidas do DOM (embora haja uma maneira de contornar isso usando diretamente o serviço de compilação. A próxima fase é a chamada de controladores e funções pré-link para todas as diretivas. é chamado, o $scope está disponível e pode ser usado. O $element injetado no controlador contém o template compilado mas não inclui o conteúdo filho transcluído (conteúdo transcluído é o conteúdo entre as tags HTML inicial e final nas quais a diretiva está Por definição, controladores em um padrão MVC simplesmente passam o modelo para a visão e definem funções para manipulação de eventos. Portanto, o controlador de uma diretiva não deve modificar o DOM da diretiva por dois motivos: viola o propósito da diretiva controlador, e o conteúdo filho transcluído não foi adicionado ao DOM. Então, o que um controlador faz além de modificar o $scope ? O controlador permite que diretivas filho se comuniquem com ª diretivas dos pais. A função do controlador em si deve ser pensada como um objeto do controlador que será passado para a função pós-link da diretiva filho se a diretiva filho o solicitar. Portanto, o controlador é normalmente usado para facilitar a comunicação diretiva criando um objeto com propriedades e métodos que podem ser usados ​​por suas diretivas irmãs e filhas. A diretiva pai não pode determinar se uma diretiva filho pode exigir seu controlador, portanto, é melhor limitar o código nesse método a funções e propriedades que podem ser usadas com segurança por diretivas filho.

Após a função do controlador, a função de pré-link é executada. A função de pré-link é misteriosa para muitas pessoas. Se você ler grande parte da documentação na Internet e em livros, as pessoas escreverão que essa função é usada apenas em raras circunstâncias e as pessoas quase nunca precisarão dela. Essas mesmas explicações, então, não dão um exemplo de uma situação em que ela poderia ser usada.

A função de pré-link não é nada complicada. Primeiro, se você revisar o código-fonte do AngularJS, encontrará um excelente exemplo da função pré-link: a diretiva ng-init a usa. Por quê? É simplesmente um ótimo método para executar código privado envolvendo o $scope ; código que não pode ser chamado por diretivas irmão e filho. Ao contrário da função do controlador, a função pré-link não é passada para as diretivas. Portanto, ele pode ser usado para executar código que modifica o $scope de sua diretiva. A diretiva ng-init faz exatamente isso. Quando a função de pré-link para ng-init é executada, ela simplesmente executa o JavaScript passado para a diretiva em relação ao $scope da diretiva. O resultado da execução está disponível através da herança prototípica do $scope para diretivas filhas durante suas execuções de funções de controlador, pré-link e pós-link, mas sem dar acesso a essas diretivas filhas para reexecutar o código no pré-link do pai. função de ligação. Além disso, a diretiva pode precisar executar outro código não relacionado ao $scope que deseja manter privado.

Alguns desenvolvedores experientes do AngularJS diriam que esse código privado ainda pode ser colocado no controlador e não ser chamado pelas diretivas filhas. Esse argumento seria verdadeiro se a diretiva fosse usada apenas pelo desenvolvedor original que a codificou, mas se a diretiva for distribuída e reutilizada por outros desenvolvedores, encapsular o código privado na função pré-link pode ser muito benéfico. Como os desenvolvedores nunca sabem como sua diretiva será reutilizada ao longo do tempo, proteger o código privado de ser executado por uma diretiva filho é uma boa abordagem para o encapsulamento do código da diretiva. Considero uma boa prática colocar código público de comunicação diretiva na função de controlador e código privado na função de pré-link. Assim como o controlador, o pré-link nunca deve fazer manipulação do DOM nem executar uma função transclude, pois o conteúdo das diretivas filhas ainda não foi vinculado.

Para cada diretiva, seu controlador e função pré-link são executados antes do controlador e função pré-link de suas diretivas filhas. Uma vez que o controlador e a fase de pré-link para todas as diretivas estiverem completos, o AngularJS inicia a fase de vinculação e executa as funções de pós-link para cada diretiva. A fase de vinculação é oposta aos fluxos de execução de compilação, controlador e pré-vinculação, começando com os nós DOM folha e subindo até o nó DOM raiz. A travessia do DOM pós-link segue principalmente um caminho de profundidade. À medida que cada diretiva filha é vinculada, sua função pós-link é executada.

A função post-link é a função mais comumente implementada em diretivas personalizadas do AngularJS. Nesta função, quase tudo razoável pode ser feito. O DOM pode ser manipulado (somente para ele mesmo e para elementos filhos), o $scope está disponível, o objeto controlador para diretivas pai pode ser usado, funções transclude podem ser executadas, etc. No entanto, existem algumas limitações. Novas diretivas não podem ser adicionadas ao DOM porque elas não serão compiladas. Além disso, todas as manipulações do DOM devem ser feitas usando as funções do DOM. Simplesmente chamar a função html no elemento DOM e passar o novo HTML removerá todos os manipuladores de eventos adicionados durante o processo de compilação. Por exemplo, estes não funcionarão como esperado:

 element.html(element.html());

ou

 element.html(element.html() + "<div>new content</div>");

O código não fará com que o HTML seja alterado, mas reatribuir a versão string dos elementos DOM removerá todos os manipuladores de eventos criados durante o processo de compilação. Normalmente, a função post-link é usada para conectar manipuladores de eventos, $watch es e $observe s.

Uma vez que todas as funções pós-link são executadas, o $scope é aplicado à estrutura DOM compilada e vinculada, e a página AngularJS ganha vida.

Gráfico de Função Diretiva

Aqui está um gráfico listando a finalidade de cada função, o que está disponível quando ela é executada e as práticas recomendadas sobre como usar cada função adequadamente.

Execução
Ordem
Diretiva
Função
DOM Transcluir $scope Chamado
por criança
1 compilar O DOM não foi compilado, mas o template foi carregado na área de conteúdo do elemento DOM. Diretivas podem ser adicionadas e removidas. O DOM pode ser manipulado com funções DOM e substituição de strings HTML. A função Transclude está disponível, mas está obsoleta e não deve ser chamada. Não disponível. A função não pode ser chamada por elementos filhos.
2 controlador O elemento DOM compilado está disponível, mas não deve ser modificado. O conteúdo filho transcluído não foi adicionado ao elemento DOM. Nenhuma alteração no DOM deve ocorrer porque este é um controlador e o conteúdo filho transcluído ainda não foi vinculado. A função Transclude está disponível, mas não deve ser chamada. $scope está disponível e pode ser usado. Os parâmetros da função são injetados usando o serviço $injector . A função é passada para as funções de vinculação da diretiva filho e pode ser chamada por elas.
3 pré-link O elemento DOM compilado está disponível, mas não deve ser modificado porque os elementos DOM da diretiva filho ainda não foram vinculados. A função Transclude está disponível, mas não deve ser chamada. $scope está disponível e pode ser modificado. A função não pode ser chamada por diretivas filhas. Mas pode chamar os controladores de diretivas pai.
4 pós-link O elemento DOM compilado e os elementos DOM da diretiva filho estão disponíveis. O DOM pode ser modificado apenas com funções DOM (sem substituição de HTML) e somente o conteúdo que não requer compilação pode ser adicionado. Nenhuma adição/remoção de diretivas é permitida. A função Transclude está disponível e pode ser chamada. $scope está disponível e pode ser usado. Não pode ser chamado pelos filhos da diretiva, mas pode chamar o controlador das diretivas pai.

Resumo

Neste tutorial sobre diretivas AngularJS, aprendemos sobre o propósito, ordem de execução e recursos e usos gerais para cada uma das quatro funções de diretiva: compile , controller , pre-link e post-link . Das quatro funções, controller e post-link são as mais usadas, mas para diretivas mais complexas que precisam ter maior controle do DOM ou precisam de um ambiente de execução de escopo privado, as funções de compilação e pré-link podem ser utilizadas.