angularjs - link - ng-href angular 4




Directivas angulares: cuándo y cómo usar compilación, controlador, enlace previo y enlace posterior (6)

Al escribir una directiva angular, se puede usar cualquiera de las siguientes funciones para manipular el comportamiento, el contenido y el aspecto del DOM en el que se declara la directiva:

  • compilar
  • controlador
  • enlace previo
  • enlace posterior

Parece que hay cierta confusión en cuanto a qué función se debe usar. Esta pregunta cubre:

Fundamentos de la directiva

  • ¿Cómo declarar las diversas funciones?
  • ¿Cuál es la diferencia entre una plantilla de origen y una plantilla de instancia ?
  • ¿En qué orden se ejecutan las funciones directivas?
  • ¿Qué más sucede entre estas llamadas de función?

Naturaleza de la función, hacer y no hacer.

  • Compile
  • Controller
  • Pre-link
  • Post-link

Preguntas relacionadas:


¿Cómo declarar las diversas funciones?

Compilar, Controlador, Pre-link y Post-link

Si una es usar las cuatro funciones, la directiva seguirá este formulario:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.
            return {
                pre: function preLink( scope, element, attributes, controller, transcludeFn ) {
                    // Pre-link code goes here
                },
                post: function postLink( scope, element, attributes, controller, transcludeFn ) {
                    // Post-link code goes here
                }
            };
        }
    };  
});

Tenga en cuenta que compile devuelve un objeto que contiene las funciones de enlace previo y posterior al enlace; en Angular lingo decimos que la función de compilación devuelve una función de plantilla .

Compilar, Controlador y Post-link

Si pre-link no es necesario, la función de compilación puede simplemente devolver la función de enlace posterior en lugar de un objeto de definición, de este modo:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.
            return function postLink( scope, element, attributes, controller, transcludeFn ) {
                    // Post-link code goes here                 
            };
        }
    };  
});

A veces, uno desea agregar un método de compile , después de que se definió el método de (publicación) link . Para esto, uno puede usar:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.

            return this.link;
        },
        link: function( scope, element, attributes, controller, transcludeFn ) {
            // Post-link code goes here
        }

    };  
});

Controlador y enlace posterior

Si no se necesita una función de compilación, se puede omitir su declaración por completo y proporcionar la función de enlace posterior bajo la propiedad de link del objeto de configuración de la directiva:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        link: function postLink( scope, element, attributes, controller, transcludeFn ) {
                // Post-link code goes here                 
        },          
    };  
});

Sin controlador

En cualquiera de los ejemplos anteriores, uno puede simplemente eliminar la función del controller si no es necesario. Entonces, por ejemplo, si solo se necesita la función de post-link , se puede usar:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        link: function postLink( scope, element, attributes, controller, transcludeFn ) {
                // Post-link code goes here                 
        },          
    };  
});

¿Cuál es la diferencia entre una plantilla de origen y una plantilla de instancia ?

El hecho de que Angular permita la manipulación de DOM significa que el marcado de entrada en el proceso de compilación a veces difiere de la salida. En particular, algunas marcas de entrada pueden clonarse unas cuantas veces (como con ng-repeat ) antes de procesarse en el DOM.

La terminología angular es un poco inconsistente, pero aún distingue dos tipos de marcas:

  • Plantilla de origen : el marcado que se va a clonar, si es necesario. Si se clona, ​​este marcado no se representará en el DOM.
  • Plantilla de instancia : el marcado real que se representará en el DOM. Si se trata de una clonación, cada instancia será un clon.

El siguiente marcado demuestra esto:

<div ng-repeat="i in [0,1,2]">
    <my-directive>{{i}}</my-directive>
</div>

La fuente html define

    <my-directive>{{i}}</my-directive>

que sirve como la plantilla de origen.

Pero como está dentro de una directiva ng-repeat , esta plantilla de origen se clonará (3 veces en nuestro caso). Estos clones son una plantilla de instancia, cada uno aparecerá en el DOM y estará vinculado al ámbito relevante.


¿Qué más sucede entre estas llamadas de función?

Las diversas funciones de la directiva se ejecutan desde otras dos funciones angulares llamadas $compile (donde se ejecuta la compile la directiva) y una función interna llamada nodeLinkFn (donde se ejecutan el controller la directiva, preLink y postLink ). Varias cosas suceden dentro de la función angular antes y después de que se llaman las funciones directivas. Quizás lo más notable es la recursión infantil. La siguiente ilustración simplificada muestra los pasos clave dentro de las fases de compilación y enlace:

Para demostrar estos pasos, usemos el siguiente código HTML:

<div ng-repeat="i in [0,1,2]">
    <my-element>
        <div>Inner content</div>
    </my-element>
</div>

Con la siguiente directiva:

myApp.directive( 'myElement', function() {
    return {
        restrict:   'EA',
        transclude: true,
        template:   '<div>{{label}}<div ng-transclude></div></div>'
    }
});

Compilar

La API de compile ve así:

compile: function compile( tElement, tAttributes ) { ... }

A menudo, los parámetros tienen el prefijo t para indicar que los elementos y los atributos proporcionados son los de la plantilla de origen, en lugar de los de la instancia.

Antes de la llamada para compile contenido transcluido (si existe) se elimina, y la plantilla se aplica a la marca. Por lo tanto, el elemento proporcionado a la función de compile se verá así:

<my-element>
    <div>
        "{{label}}"
        <div ng-transclude></div>
    </div>
</my-element>

Observe que el contenido transcluido no se reinserta en este punto.

Tras la llamada a la .compile la directiva, Angular atravesará todos los elementos secundarios, incluidos aquellos que pueden haber sido introducidos por la directiva (los elementos de la plantilla, por ejemplo).

Creación de instancias

En nuestro caso, se crearán tres instancias de la plantilla de origen anterior (por ng-repeat ). Por lo tanto, la siguiente secuencia se ejecutará tres veces, una por instancia.

Controlador

La API del controller implica:

controller: function( $scope, $element, $attrs, $transclude ) { ... }

Al ingresar a la fase de enlace, la función de enlace devuelta a través de $compile ahora cuenta con un alcance.

Primero, la función de enlace crea un alcance secundario ( scope: true ) o un alcance aislado ( scope: {...} ) si se solicita.

Luego se ejecuta el controlador, provisto con el alcance del elemento de instancia.

Pre-enlace

La API de pre-link ve así:

function preLink( scope, element, attributes, controller ) { ... }

Prácticamente no pasa nada entre la llamada al .controller la directiva y la función .preLink . Angular todavía proporciona recomendaciones sobre cómo se debe utilizar cada uno.

Después de la llamada .preLink , la función de enlace atravesará cada elemento .preLink llamará a la función de enlace correcta y adjuntará el alcance actual (que sirve como el ámbito principal para los elementos secundarios).

Enlace posterior

La API post-link es similar a la de la función de pre-link :

function postLink( scope, element, attributes, controller ) { ... }

Tal vez valga la pena notar que una vez que se llama la función .postLink una directiva, el proceso de enlace de todos sus elementos .postLink ha completado, incluidas todas las funciones .postLink los niños.

Esto significa que cuando se llama a .postLink , los niños están 'en vivo' y están listos. Esto incluye:

  • el enlace de datos
  • transclusión aplicada
  • alcance adjunto

La plantilla en esta etapa se verá así:

<my-element>
    <div class="ng-binding">
        "{{label}}"
        <div ng-transclude>                
            <div class="ng-scope">Inner content</div>
        </div>
    </div>
</my-element>

Función de compilación

La función de compile cada directiva solo se llama una vez, cuando Angular bootstraps.

Oficialmente, este es el lugar para realizar manipulaciones de plantillas (de origen) que no implican alcance o enlace de datos.

Principalmente, esto se hace con fines de optimización; Considere el siguiente marcado:

<tr ng-repeat="raw in raws">
    <my-raw></my-raw>
</tr>

La directiva <my-raw> representará un conjunto particular de marcado DOM. Entonces podemos:

  • Permita que ng-repeat duplique la plantilla de origen ( <my-raw> ) y luego modifique el marcado de cada plantilla de instancia (fuera de la función de compile ).
  • Modifique la plantilla de origen para incluir el marcado deseado (en la función de compile ) y luego permita que ng-repeat duplique.

Si hay 1000 elementos en la colección de raws , la última opción puede ser más rápida que la anterior.

Hacer:

  • Manipular el marcado para que sirva de plantilla a instancias (clones).

No haga

  • Adjuntar controladores de eventos.
  • Inspeccionar elementos secundarios.
  • Establecer observaciones sobre los atributos.
  • Configurar relojes en el ámbito de aplicación.

Función de enlace posterior

Cuando se llama a la función de post-link , se han llevado a cabo todos los pasos anteriores: enlace, transclusión, etc.

Este suele ser un lugar para manipular aún más el DOM renderizado.

Hacer:

  • Manipular elementos DOM (renderizados, y por lo tanto instanciados).
  • Adjuntar controladores de eventos.
  • Inspeccionar elementos secundarios.
  • Establecer observaciones sobre los atributos.
  • Configurar relojes en el ámbito de aplicación.

Función de pre-enlace

La función de pre-link cada directiva se llama cada vez que se crea una instancia de un nuevo elemento relacionado.

Como se vio anteriormente en la sección de orden de compilación, pre-link funciones de pre-link se denominan padre-luego-hijo, mientras que post-link funciones de post-link se llaman child-then-parent .

La función de pre-link rara vez se utiliza, pero puede ser útil en escenarios especiales; por ejemplo, cuando un controlador secundario se registra a sí mismo con el controlador principal, pero el registro tiene que ser de un modo parent-then-child ( ngModelController hace las cosas de esta manera).

No haga:

  • Inspeccione elementos secundarios (es posible que aún no se hayan procesado, estén vinculados al alcance, etc.).






angularjs-directive