angularjs - templateurl - Link vs compile vs controller




templateurl angularjs (4)

Quando si crea una direttiva, è possibile inserire il codice nel compilatore, nella funzione di collegamento o nel controller.

Nei documenti, spiegano che:

  • le funzioni di compilazione e collegamento vengono utilizzate in diverse fasi del ciclo angolare
  • i controller sono condivisi tra le direttive

Tuttavia, per me non è chiaro, che tipo di codice dovrebbe andare dove.

Ad esempio: Posso creare funzioni in compilazione e averle associate allo scope in link o solo allegare funzioni all'oscilloscopio nel controller?

In che modo i controllori sono condivisi tra le direttive, se ciascuna direttiva può avere un proprio controllore? I controller sono realmente condivisi o sono solo le proprietà dell'ambito?


Inoltre, un buon motivo per usare una funzione controller vs link (dato che entrambi hanno accesso a scope, elemento e attrs) è perché puoi trasferire qualsiasi servizio o dipendenza disponibile in un controller (e in qualsiasi ordine), mentre non puoi farlo con la funzione link. Notare le diverse firme:

controller: function($scope, $exceptionHandler, $attr, $element, $parse, $myOtherService, someCrazyDependency) {...

vs.

link: function(scope, element, attrs) {... //no services allowed

Una directive consente di estendere il vocabolario HTML in modo dichiarativo per la creazione di componenti Web. L'attributo ng-app è una direttiva, quindi è ng-controller e tutti gli ng- prefixed attributes ng-controller . Le direttive possono essere attributes , tags o names class , comments .

Come nascono le direttive ( compilation e instantiation )

Compilare: useremo la funzione di compile per manipulate il DOM prima del rendering e restituire una funzione di link (che gestirà il collegamento per noi). Questo è anche il posto dove mettere tutti i metodi che devono essere condivisi con tutte le instances di questa direttiva.

link: useremo la funzione link per registrare tutti gli ascoltatori su uno specifico elemento DOM (che è clonato dal modello) e impostare i nostri collegamenti alla pagina.

Se impostati nella funzione compile() , sarebbero stati impostati una sola volta (che è spesso ciò che si desidera). Se impostati nella funzione link() , verrebbero impostati ogni volta che l'elemento HTML è associato ai dati nel oggetto.

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

app.directive("simple", function(){
   return {
     restrict: "EA",
     transclude:true,
     template:"<div>{{label}}<div ng-transclude></div></div>",        
     compile: function(element, attributes){  
     return {
             pre: function(scope, element, attributes, controller, transcludeFn){

             },
             post: function(scope, element, attributes, controller, transcludeFn){

             }
         }
     },
     controller: function($scope){

     }
   };
});

Compile funzione Compile restituisce la funzione pre e post link. Nella funzione pre-link abbiamo il modello di istanza e anche l'ambito dal controller , ma ancora il modello non è legato all'ambito e non ha ancora contenuto escluso.

Post funzione post link è dove il link post è l'ultima funzione da eseguire. Ora la transclusion è completa, the template is linked to a scope e la view will update with data bound values after the next digest cycle . L'opzione di link è solo una scorciatoia per impostare una funzione di post-link .

controller: il controllore direttiva può essere passato a un'altra fase di collegamento / compilazione della direttiva. Può essere iniettato in altre direttive come mezzo da utilizzare nella comunicazione inter-direttiva.

Devi specificare il nome della direttiva da richiedere - Dovrebbe essere associato allo stesso elemento o al suo genitore. Il nome può essere preceduto da:

? – Will not raise any error if a mentioned directive does not exist.
^ – Will look for the directive on parent elements, if not available on the same element.

Usa parentesi quadre ['directive1′, 'directive2′, 'directive3′] per richiedere un controller di più direttive.

var app = angular.module('app', []);

app.controller('MainCtrl', function($scope, $element) {
});

app.directive('parentDirective', function() {
  return {
    restrict: 'E',
    template: '<child-directive></child-directive>',
    controller: function($scope, $element){
      this.variable = "Hi Vinothbabu"
    }
  }
});

app.directive('childDirective', function() {
  return {
    restrict:  'E',
    template: '<h1>I am child</h1>',
    replace: true,
    require: '^parentDirective',
    link: function($scope, $element, attr, parentDirectCtrl){
      //you now have access to parentDirectCtrl.variable
    }
  }
});

questo è un buon esempio per capire le fasi direttive http://codepen.io/anon/pen/oXMdBQ?editors=101

var app = angular.module('myapp', [])

app.directive('slngStylePrelink', function() {
    return {
        scope: {
            drctvName: '@'
        },
        controller: function($scope) {
            console.log('controller for ', $scope.drctvName);
        },
        compile: function(element, attr) {
            console.log("compile for ", attr.name)
            return {
                post: function($scope, element, attr) {
                    console.log('post link for ', attr.name)
                },
                pre: function($scope, element, attr) {
                    $scope.element = element;
                    console.log('pre link for ', attr.name)
                        // from angular.js 1.4.1
                    function ngStyleWatchAction(newStyles, oldStyles) {
                        if (oldStyles && (newStyles !== oldStyles)) {
                            forEach(oldStyles, function(val, style) {
                                element.css(style, '');
                            });
                        }
                        if (newStyles) element.css(newStyles);
                    }

                    $scope.$watch(attr.slngStylePrelink, ngStyleWatchAction, true);

                    // Run immediately, because the watcher's first run is async
                    ngStyleWatchAction($scope.$eval(attr.slngStylePrelink));
                }
            };
        }
    };
});

html

<body ng-app="myapp">
    <div slng-style-prelink="{height:'500px'}" drctv-name='parent' style="border:1px solid" name="parent">
        <div slng-style-prelink="{height:'50%'}" drctv-name='child' style="border:1px solid red" name='child'>
        </div>
    </div>
</body>

Compilare:

Questa è la fase in cui Angular compila effettivamente la tua direttiva. Questa funzione di compilazione viene chiamata una sola volta per ogni riferimento alla direttiva data. Ad esempio, supponiamo di utilizzare la direttiva ng-repeat. ng-repeat dovrà cercare l'elemento a cui è collegato, estrarre il frammento html a cui è collegato e creare una funzione template.

Se hai usato HandleBars, template di underscore o equivalenti, è come compilare i loro template per estrarre una funzione template. A questa funzione template si passano dati e il valore di ritorno di tale funzione è l'html con i dati nelle posizioni giuste.

La fase di compilazione è quella fase in Angular che restituisce la funzione template. Questa funzione di modello angolare è chiamata funzione di collegamento.

Fase di collegamento:

La fase di collegamento è dove si allega i dati ($ scope) alla funzione di collegamento e dovrebbe restituire l'html collegato. Dato che la direttiva specifica anche dove va questo html o cosa cambia, è già bello andare. Questa è la funzione in cui si desidera apportare modifiche all'HTML collegato, ovvero l'html a cui sono già associati i dati. In angolare se si scrive codice nella funzione di collegamento generalmente si tratta della funzione post-link (di default). È una sorta di callback che viene chiamato dopo che la funzione di collegamento ha collegato i dati con il modello.

Controller:

Il controller è un luogo in cui si inserisce una logica specifica per la direttiva. Questa logica può andare anche nella funzione di collegamento, ma in tal caso dovresti mettere quella logica sull'oscilloscopio per renderlo "condivisibile". Il problema con questo è che si corrompe l'ambito con le direttive che non sono realmente previste. Quindi qual è l'alternativa se due direttive vogliono parlarsi / cooperare tra loro? Ovviamente potresti mettere tutta quella logica in un servizio e poi far dipendere entrambe queste direttive da quel servizio, ma questo porta solo un'altra dipendenza. L'alternativa è fornire un controller per questo ambito (di solito isolare l'ambito?) E quindi questo controller viene iniettato in un'altra direttiva quando quella direttiva "richiede" l'altro. Vedi schede e riquadri sulla prima pagina di angularjs.org per un esempio.





angularjs-directive