tipos personalizadas directivas crear javascript angularjs angularjs-directive

javascript - personalizadas - Angular JS: ¿Cuál es la necesidad de la función de enlace de la directiva cuando ya teníamos el controlador de la directiva con alcance?



directivas personalizadas angularjs (3)

Por qué se necesitan controladores

La diferencia entre el link y el controller entra en juego cuando desea anidar directivas en su DOM y exponer funciones de la API de la directiva principal a las anidadas.

De los docs :

Mejores prácticas: use el controlador cuando quiera exponer una API a otras directivas. De lo contrario, use el enlace.

Digamos que quiere tener dos directivas my-form y my-text-input y quiere que my-text-input directiva my-text-input aparezca solo dentro de my-form y en ninguna otra parte.

En ese caso, dirá al definir la directiva my-text-input que requiere un controlador del elemento DOM parent utilizando el argumento require , como este: require: ''^myForm'' . Ahora el controlador del elemento padre se injected en la función de link como el cuarto argumento, siguiendo $scope, element, attributes . Puede llamar a funciones en ese controlador y comunicarse con la directiva principal.

Además, si no se encuentra dicho controlador, se generará un error.

Por qué utilizar el enlace en absoluto

No hay necesidad real de utilizar la función de link si se está definiendo el controller ya que $scope está disponible en el controller . Además, al definir tanto el link como el controller , es necesario tener cuidado con el orden de invocación de los dos (el controller se ejecuta antes).

Sin embargo, de acuerdo con la forma Angular , la mayoría de las manipulaciones DOM y vinculaciones bidireccionales usando $watchers usualmente se realizan en la función de link mientras que la API para niños y $scope manipulación se realiza en el controller . Esta no es una regla difícil y rápida, pero al hacerlo, el código será más modular y ayudará a separar las preocupaciones (el controlador mantendrá el estado de la directive y la función de link mantendrá los enlaces externos del DOM +).

Necesito realizar algunas operaciones en el alcance y la plantilla. Parece que puedo hacer eso en la función de link o en la función del controller (ya que ambos tienen acceso al alcance).

¿Cuándo es el caso cuando tengo que usar la función de link y no el 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 */ } }; }

Además, entiendo que el link es el mundo no angular. Entonces, puedo usar $watch , $digest y $apply .

¿Cuál es el significado de la función de link , cuando ya teníamos el controlador?


Después de mi lucha inicial con las funciones de link y controller y de haber leído bastante sobre ellas, creo que ahora tengo la respuesta.

Primero vamos a entender ,

¿Cómo funcionan las directivas angulares en pocas palabras?

  • Comenzamos con una plantilla (como una cadena o cargada en una cadena)

    var templateString = ''<div my-directive>{{5 + 10}}</div>'';

  • Ahora, esta templateString está envuelta como un elemento angular

    var el = angular.element(templateString);

  • Con el , ahora lo compilamos con $compile para recuperar la función de enlace .

    var l = $compile(el)

    Esto es lo que sucede,

    • $compile recorre toda la plantilla y recopila todas las directivas que reconoce.
    • Todas las directivas que se descubren se compilan de forma recursiva y se recopilan sus funciones de link .
    • Luego, todas las funciones de link se envuelven en una nueva función de link y se devuelven como l .
  • Finalmente, proporcionamos la función de scope a esta función l (enlace) que además ejecuta las funciones de enlace envuelto con este scope y sus elementos correspondientes.

    l(scope)

  • Esto agrega la template como un nuevo nodo al DOM e invoca el controller que agrega sus relojes al alcance que se comparte con la plantilla en DOM.

Comparando compilar vs enlace vs controlador :

  • Cada directiva se compila solo una vez y la función de enlace se conserva para su reutilización. Por lo tanto, si hay algo aplicable a todas las instancias de una directiva debe realizarse dentro de la función de compile la directiva.

  • Ahora, después de la compilación, tenemos la función de link que se ejecuta al unir la plantilla al DOM . Por lo tanto, realizamos todo lo que es específico para cada instancia de la directiva. Por ejemplo: adjuntar eventos , mutar la plantilla en función del alcance , etc.

  • Finalmente, el controlador debe estar disponible para ser activo y reactivo mientras la directiva funciona en el DOM (después de conectarse). Por lo tanto:

    (1) Después de configurar la vista [ V ] (es decir, la plantilla) con el enlace. $scope es nuestro $controller [ M ] y $controller es nuestro [ C ] en MVC

    (2) Aproveche el enlace bidireccional con $ scope configurando relojes.

    (3) Se espera agregar relojes $scope en el controlador ya que esto es lo que está viendo la plantilla durante el tiempo de ejecución.

    (4) Finalmente, el controller también se usa para poder comunicarse entre directivas relacionadas. (Como el ejemplo de myTabs en https://docs.angularjs.org/guide/directive )

    (5) Es cierto que podríamos haber hecho todo esto en la función de link también, pero se trata de la separación de las preocupaciones .

Por lo tanto, finalmente tenemos lo siguiente que se adapta perfectamente a todas las piezas:


La función / objeto del controller representa una abstracción model-view-controller (MVC). Si bien no hay nada nuevo que escribir sobre MVC, sigue siendo la ventaja más significativa de angular: dividir las preocupaciones en piezas más pequeñas. Y eso es todo, nada más, así que si necesita reaccionar a los cambios del Model que vienen de View the Controller es la persona adecuada para hacer ese trabajo.

La historia sobre la función de link es diferente, viene de una perspectiva diferente a MVC. Y es realmente esencial, una vez que queremos cruzar los límites de un controller/model/view (plantilla) .

Comencemos con los parámetros que pasan a la función de link :

function link(scope, element, attrs) {

  • scope es un objeto de alcance angular.
  • elemento es el elemento jqLite envuelto que coincide con esta directiva.
  • attrs es un objeto con los nombres de atributos normalizados y sus valores correspondientes.

Para poner el link en el contexto, debemos mencionar que todas las directivas están pasando por estos pasos del proceso de inicialización: compilar , vincular . Un extracto de Brad Green y Shyam Seshadri libro Angular JS :

Fase de compilación (una hermana de enlace, vamos a mencionarlo aquí para obtener una imagen clara):

En esta fase, Angular recorre el DOM para identificar todas las directivas registradas en la plantilla. Para cada directiva, transforma el DOM según las reglas de la directiva (plantilla, reemplazar, transcluir, etc.) y llama a la función de compilación, si existe. El resultado es una función de plantilla compilada

Fase de enlace :

Para que la vista sea dinámica, Angular ejecuta una función de enlace para cada directiva. Las funciones de enlace normalmente crean oyentes en el DOM o el modelo. Estos oyentes mantienen la vista y el modelo sincronizados en todo momento.

Un buen ejemplo de cómo usar el link se puede encontrar aquí: docs . Vea el ejemplo: Crear una directiva que manipule el DOM , que inserta un "fecha y hora" en la página, actualizado cada segundo.

Solo un pequeño fragmento de esa rica fuente de arriba, que muestra la verdadera manipulación con DOM. Hay una función enganchada al $ timeout service, y también se borra en su llamada al destructor para evitar fugas de memoria

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