JS angolare: qual è la necessità della funzione di collegamento della direttiva quando avevamo già il controller della direttiva con ambito?


199

Devo eseguire alcune operazioni sull'ambito e sul modello. Sembra che io possa farlo nella linkfunzione o nella controllerfunzione (poiché entrambi hanno accesso all'ambito).

Quando devo utilizzare la linkfunzione e non il controller?

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 */ }
    };
}

Inoltre, capisco che linkè il mondo non angolare. Quindi, posso usare $watch, $digeste $apply.

Qual è il significato della linkfunzione, quando avevamo già il controller?


9
Che cosa si intende per " Inoltre, capisco che collegamento è il mondo non-angolare. Quindi, posso usare $watch, $digeste $apply. "?
musically_ut,

2
All'interno linknon vediamo alcuna magia angolare. cioè non ci sono attacchi a 2 vie, ecc. Solo che abbiamo api angolari disponibili per l'uso.
Yugal Jindle

Risposte:


299

Dopo la mia prima lotta con la linke controllerfunzioni e la lettura di un bel po 'su di loro, penso che ora ho la risposta.

Prima di tutto capiamo ,

Come funzionano le direttive angolari in breve:

  • Iniziamo con un modello (come stringa o caricato in una stringa)

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

  • Ora, questo templateStringè avvolto come un elemento angolare

    var el = angular.element(templateString);

  • Con el, ora lo compiliamo $compileper ripristinare la funzione di collegamento .

    var l = $compile(el)

    Ecco cosa succede,

    • $compile esamina l'intero modello e raccoglie tutte le direttive che riconosce.
    • Tutte le direttive che vengono scoperte vengono compilate in modo ricorsivo e le loro linkfunzioni vengono raccolte.
    • Quindi, tutte le linkfunzioni sono racchiuse in una nuova linkfunzione e restituite come l.
  • Infine, forniamo la scopefunzione a questa funzione l(collegamento) che esegue ulteriormente le funzioni di collegamento avvolto con questo scopee i loro elementi corrispondenti.

    l(scope)

  • Ciò aggiunge templatecome un nuovo nodo a DOMe invoca il controllerquale aggiunge i suoi watch all'ambito che è condiviso con il modello in DOM.

inserisci qui la descrizione dell'immagine

Confronto tra compilazione vs collegamento vs controller :

  • Ogni direttiva viene compilata una sola volta e la funzione di collegamento viene conservata per il riutilizzo. Pertanto, se esiste qualcosa applicabile a tutte le istanze di una direttiva dovrebbe essere eseguita all'interno della compilefunzione della direttiva .

  • Ora, dopo la compilazione, abbiamo una linkfunzione che viene eseguita durante il collegamento del modello al DOM . Pertanto, eseguiamo tutto ciò che è specifico per ogni istanza della direttiva. Ad esempio: allegare eventi , mutare il modello in base all'ambito , ecc.

  • Infine, il controller dovrebbe essere disponibile per essere attivo e reattivo mentre la direttiva funziona sul DOM(dopo essersi collegato). Perciò:

    (1) Dopo aver impostato la vista [ V ] (es. Modello) con collegamento. $scopeè la nostra [ M ] ed $controllerè la nostra [ C ] in MVC

    (2) Approfitta dell'associazione a 2 vie con $ scope impostando gli orologi.

    (3) Gli $scopeorologi dovrebbero essere aggiunti nel controller poiché questo è ciò che sta guardando il modello durante il runtime.

    (4) Infine, controllerviene anche utilizzato per essere in grado di comunicare tra le direttive correlate. (Come myTabsesempio in https://docs.angularjs.org/guide/directive )

    (5) È vero che avremmo potuto fare tutto ciò anche nella linkfunzione, ma si tratta della separazione delle preoccupazioni .

Pertanto, finalmente abbiamo quanto segue che si adatta perfettamente a tutti i pezzi:

inserisci qui la descrizione dell'immagine


5
Ho anche trovato utile questo articolo per comprendere l'ordine di esecuzione qui: la nitidezza delle funzioni di compilazione e collegamento all'interno delle direttive AngularJS
BobbyA

4
Ottima spiegazione Vorrei menzionare che il controller viene chiamato prima della funzione di collegamento.
jsbisht,

38
il controller viene eseguito prima del collegamento
Royi Namir il

10
Mi fa infuriare il fatto che Stack Overflow richieda che le modifiche siano di almeno 6 caratteri, quindi non mi consente di correggere l'ortografia di inserire questa risposta.
user1886323

79

Perché sono necessari i controller

La differenza tra linke controllerentra in gioco quando vuoi annidare le direttive nel tuo DOM ed esporre le funzioni API dalla direttiva padre a quelle nidificate.

Dai documenti :

Best practice: utilizzare il controller quando si desidera esporre un'API ad altre direttive. Altrimenti usa il link.

Supponiamo che tu voglia avere due direttive my-forme my-text-inputdesideri che la my-text-inputdirettiva appaia solo all'interno my-forme in nessun altro luogo.

In questo caso, si dirà durante la definizione della direttiva my-text-inputche richiede un controller dal parentelemento DOM utilizzando la richiedono argomento, in questo modo: require: '^myForm'. Ora il controller dall'elemento genitore entrerà injectednella linkfunzione come quarto argomento, a seguire $scope, element, attributes. È possibile chiamare funzioni su quel controller e comunicare con la direttiva padre.

Inoltre, se tale controller non viene trovato, verrà generato un errore.

Perché usare il collegamento a tutti

Non è necessario utilizzare la linkfunzione se si sta definendo il controllerpoiché il $scopeè disponibile sul controller. Inoltre, mentre si definiscono entrambi linke controller, è necessario fare attenzione all'ordine di invocazione dei due ( controllereseguito prima).

Tuttavia, in linea con il modo angolare , la maggior parte della manipolazione del DOM e dell'utilizzo dell'associazione a 2 vie $watchersviene generalmente eseguita nella linkfunzione mentre l'API per i bambini e la $scopemanipolazione viene eseguita nel controller. Questa non è una regola rigida e veloce, ma farlo renderà il codice più modulare e aiuterà a separare le preoccupazioni (il controller manterrà lo directivestato e la linkfunzione manterrà i DOMbinding + esterni).


È fantastico. Ora, puoi aiutarmi con la seconda parte della domanda?
Yugal Jindle

Voglio dire, dato che esisteva il controller che avrebbe potuto essere utilizzato per comunicare con altre direttive. Quindi, di cosa aveva bisogno link?
Yugal Jindle

1
La tua risposta in qualche modo non risponde alla domanda reale.
Yugal Jindle

1
Ci sono problemi che si verificano quando definiamo un controller? Perché vorrò inventare una funzione completamente nuova solo per evitare di definire il controller?
Yugal Jindle

1
sembra che il link di @scalaGirl non funzioni più
Minato,

17

La controllerfunzione / oggetto rappresenta un controller-view-controller (MVC) di astrazione. Mentre non c'è nulla di nuovo da scrivere su MVC, è ancora il vantaggio più significativo dell'angolare: dividere le preoccupazioni in pezzi più piccoli. E questo è tutto, niente di più, quindi se avete bisogno di reagire a Modelcambiamenti provenienti dal Viewil Controllerè il diritto persona a fare quel lavoro.

La storia della linkfunzione è diversa, viene da una prospettiva diversa rispetto a MVC. Ed è davvero essenziale, una volta che vogliamo oltrepassare i confini di un controller/model/view (modello) .

Cominciamo con i parametri che vengono passati nella linkfunzione:

function link(scope, element, attrs) {
  • scope è un oggetto scope angolare.
  • L'elemento è l'elemento avvolto in jqLite a cui questa direttiva corrisponde.
  • attrs è un oggetto con i nomi degli attributi normalizzati e i loro valori corrispondenti.

Per linkentrare nel contesto, dovremmo menzionare che tutte le direttive stanno attraversando questo processo di inizializzazione: compilazione , collegamento . Un estratto del libro Angular JS di Brad Green e Shyam Seshadri :

Fase di compilazione (una sorella del link, menzioniamola qui per avere un'immagine chiara):

In questa fase, Angular accompagna il DOM per identificare tutte le direttive registrate nel modello. Per ogni direttiva, quindi trasforma il DOM in base alle regole della direttiva (modello, rimpiazzare, escludere e così via) e chiama la funzione di compilazione se esiste. Il risultato è una funzione modello compilata,

Fase di collegamento :

Per rendere dinamica la vista, Angular esegue quindi una funzione di collegamento per ogni direttiva. Le funzioni di collegamento in genere creano listener sul DOM o sul modello. Questi listener mantengono sempre la vista e il modello sincronizzati.

Un buon esempio su come utilizzare linkpotrebbe essere trovato qui: Creazione di direttive personalizzate . Vedi l'esempio: Creazione di una direttiva che manipola il DOM , che inserisce una "data-ora" nella pagina, aggiornata ogni secondo.

Solo un frammento molto breve di quella ricca fonte sopra, che mostra la vera manipolazione con DOM. C'è una funzione agganciata al servizio $ timeout e inoltre viene cancellata nella sua chiamata distruttore per evitare perdite di 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);
 });

 ...

3
Sembra che tu abbia confrontato compilere link. Si chiedono perché linkquando abbiamo già avutocontroller
Yugal Jindle

Ho esteso la risposta per descrivere anche il controller in modo più dettagliato. Ora i concetti del controllervs linkdovrebbero essere più chiari ...
Radim Köhler il

1
Posso cercare di accontentarmi di quella spiegazione. Ma sembra essere un po 'sfocato lì. Sarebbe bello se qualcuno della stessa squadra angolare potesse parlare per questo, proiettando dove lo vedono andare - verso linko verso controller.
Yugal Jindle

1
Questa è l'unica parte che voglio capire (quando non è sufficiente?). Inoltre, ottengo tutti i vantaggi dell'angolazione controllered linkè relativamente brutto. Quindi, la squadra angolare deve avere una buona ragione per questo invece che solo un'opzione.
Yugal Jindle

1
Domanda: quando il controller non è sufficiente? Ans: Quando hai bisogno di un'esperienza fuori dagli angoli, come usare un plugin JQuery o usare la funzione JQlite come menzionato nel documento ( docs.angularjs.org/api/ng/function/angular.element:) , allora avresti bisogno link
Hasteq
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.