Tutorial AngularJS: demistificare le direttive personalizzate

Pubblicato: 2022-03-11

Con la rapida crescita di JavaScript come linguaggio full stack, sempre più applicazioni utilizzano framework che consentono al browser Web di gestire più elaborazioni dell'interfaccia utente come l'associazione dei dati, la gestione delle visualizzazioni dei dati, la trasformazione dei dati e molti altri servizi. Uno dei framework più capaci, estensibili e popolari è AngularJS e uno dei componenti più utili del framework AngularJS è qualcosa chiamato direttiva . AngularJS fornisce molte direttive utili e, cosa ancora più importante, fornisce un ricco framework per la creazione di direttive personalizzate.

Che cos'è una direttiva? Per dirla semplicemente, le direttive sono funzioni JavaScript che manipolano e aggiungono comportamenti agli elementi HTML DOM. Le direttive possono essere molto semplicistiche o estremamente complicate. Pertanto, è fondamentale avere una solida conoscenza delle loro numerose opzioni e funzioni che le manipolano.

In questo tutorial, verranno esplorate le quattro funzioni che vengono eseguite come una direttiva e applicate al DOM e verranno forniti degli esempi. Questo post presuppone una certa familiarità con AngularJS e le direttive personalizzate. Se sei un nuovo utente di Angular, potresti goderti un tutorial sulla creazione della tua prima app AngularJS.

Le quattro funzioni del ciclo di vita della direttiva AngularJS

Ci sono molte opzioni che possono essere configurate e il modo in cui queste opzioni sono correlate tra loro è importante. Ogni direttiva subisce qualcosa di simile a un ciclo di vita mentre AngularJS compila e collega il DOM. Il ciclo di vita della direttiva inizia e termina all'interno del processo di bootstrap di AngularJS, prima del rendering della pagina. Nel ciclo di vita di una direttiva, ci sono quattro funzioni distinte che possono essere eseguite se sono definite. Ciascuno consente allo sviluppatore di controllare e personalizzare la direttiva in diversi punti del ciclo di vita.

Le quattro funzioni sono: compilazione , controllore , pre-link e post-link .

La funzione di compilazione consente alla direttiva di manipolare il DOM prima che venga compilato e collegato, consentendogli così di aggiungere/rimuovere/cambiare direttive, nonché aggiungere/rimuovere/cambiare altri elementi DOM.

La funzione di controllo facilita la comunicazione direttiva. Le direttive fratelli e figli possono richiedere al responsabile del trattamento dei loro fratelli e genitori di comunicare informazioni.

La funzione di pre-link consente la manipolazione dell'ambito $ privato prima dell'inizio del processo di post-link.

Il metodo post-link è il principale metodo di lavoro della direttiva.

Nella direttiva, viene eseguita la manipolazione del DOM post-compilazione, vengono configurati i gestori di eventi, così come gli orologi e altre cose. Nella dichiarazione della direttiva, le quattro funzioni sono così definite.

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

Comunemente, non tutte le funzioni sono necessarie. Nella maggior parte dei casi, gli sviluppatori creeranno semplicemente un controller e una funzione di post-link seguendo lo schema seguente.

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

In questa configurazione, link si riferisce alla funzione post-link .

Indipendentemente dal fatto che tutte o alcune delle funzioni siano definite, il loro ordine di esecuzione è importante, in particolare la loro esecuzione rispetto al resto dell'applicazione AngularJS.

Esecuzione della funzione della direttiva AngularJS rispetto ad altre direttive

Considera il seguente snippet HTML con le direttive parentDir , childDir e grandChildDir applicate al frammento HTML.

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

L'ordine di esecuzione delle funzioni all'interno di una direttiva, e rispetto ad altre direttive, è il seguente:

  • Fase di compilazione
    • Funzione di compilazione : parentDir
    • Funzione di compilazione : childDir
    • Funzione di compilazione : grandChildDir
  • Controller e fase di pre-collegamento
    • Funzione controller : parentDir
    • Funzione di pre-collegamento : parentDir
    • Funzione controller : childDir
    • Funzione di pre-collegamento : childDir
    • Funzione controller : grandChildDir
    • Funzione di pre-collegamento : grandChildDir
  • Fase post-collegamento
    • Funzione Post-Link : grandChildDir
    • Funzione Post-Link : childDir
    • Funzione Post-Link : parentDir

Tutorial sulla funzione della direttiva AngularJS - ordine di esecuzione relativo ad altre direttive.

Spiegazione della funzione della direttiva AngularJS: Deep Dive

La fase di compilazione avviene prima. In sostanza, la fase di compilazione collega i listener di eventi agli elementi DOM. Ad esempio, se un particolare elemento DOM è associato a una proprietà $scope , all'elemento DOM viene applicato il listener di eventi che ne consente l'aggiornamento con il valore della proprietà $scope . Il processo di compilazione inizia con l'elemento DOM radice da cui è stata avviata l'applicazione AngularJS e attraversa i rami del DOM utilizzando un primo attraversamento in profondità, compilando prima un genitore poi i suoi figli fino ai nodi foglia.

Una volta completata la compilazione, le direttive non possono più essere aggiunte o rimosse dal DOM (sebbene ci sia un modo per aggirare questo problema utilizzando direttamente il servizio di compilazione. La fase successiva è la chiamata dei controller e delle funzioni di pre-link per tutte le direttive. Quando il controller viene chiamato, l' ambito $ è disponibile e può essere utilizzato. L' elemento $ iniettato nel controller contiene il modello compilato ma non include il contenuto figlio trascluso (il contenuto trascluso è il contenuto tra i tag HTML di inizio e fine su cui è applicato). Per definizione, i controller in un pattern MVC passano semplicemente il modello alla vista e definiscono le funzioni per la gestione degli eventi. Pertanto, il controller di una direttiva non dovrebbe modificare il DOM della direttiva per due motivi: viola lo scopo della direttiva controller e il contenuto figlio trascluso non è stato aggiunto al DOM. Quindi cosa fa un controller oltre a modificare l' ambito $ ? Il controller consente alle direttive figlio di comunicare wi le direttive del genitore. La funzione controller stessa dovrebbe essere considerata come un oggetto controller che verrà passato alla funzione post-link della direttiva figlio se la direttiva figlio lo richiede. Pertanto, il controller viene in genere utilizzato per facilitare la comunicazione delle direttive creando un oggetto con proprietà e metodi che possono essere utilizzati dalle sue direttive di pari livello e figlio. La direttiva padre non può determinare se una direttiva figlio può richiedere il suo controller, quindi è meglio limitare il codice in questo metodo a funzioni e proprietà che possono essere utilizzate in sicurezza dalle direttive figlio.

Dopo la funzione controller, viene eseguita la funzione di pre-link. La funzione di pre-link è misteriosa per molte persone. Se leggi gran parte della documentazione su Internet e nei libri, le persone scrivono che questa funzione viene utilizzata solo in rare circostanze e le persone non ne avranno quasi mai bisogno. Quelle stesse spiegazioni poi non forniscono un esempio di una situazione in cui potrebbe essere utilizzato.

La funzione di pre-link non è affatto complicata. Innanzitutto, se esamini il codice sorgente di AngularJS troverai un ottimo esempio della funzione pre-link: la direttiva ng-init la usa. Come mai? È semplicemente un ottimo metodo per eseguire codice privato che coinvolge $scope ; codice che non può essere chiamato da direttive di pari livello e figlio. A differenza della funzione controller, la funzione pre-link non viene trasmessa nelle direttive. Pertanto, può essere utilizzato per eseguire codice che modifica l' ambito $ della sua direttiva. La direttiva ng-init fa esattamente questo. Quando viene eseguita la funzione di pre-link per ng-init , esegue semplicemente il JavaScript passato nella direttiva contro $scope della direttiva. Il risultato dell'esecuzione è disponibile tramite l'ereditarietà prototipica di $scope per le direttive figlio durante le esecuzioni delle funzioni controller, pre-link e post-link, ma senza dare accesso a tali direttive figlio per rieseguire il codice nella pre- funzione di collegamento. Inoltre, la direttiva potrebbe dover eseguire altro codice non correlato all'ambito $ che desidera mantenere privato.

Alcuni sviluppatori AngularJS esperti direbbero che questo codice privato potrebbe ancora essere inserito nel controller e quindi non chiamato dalle direttive figlio. Tale argomento sarebbe valido se la direttiva verrà utilizzata solo dallo sviluppatore originale che l'ha codificata, ma se la direttiva verrà distribuita e riutilizzata da altri sviluppatori, l'incapsulamento del codice privato nella funzione pre-link potrebbe essere molto vantaggioso. Poiché gli sviluppatori non sanno mai come la loro direttiva verrà riutilizzata nel corso del tempo, proteggere il codice privato dall'esecuzione da parte di una direttiva figlio è un buon approccio all'incapsulamento del codice della direttiva. Ritengo che sia una buona pratica inserire il codice pubblico di comunicazione direttiva nella funzione controller e il codice privato nella funzione pre-link. Come il controller, il pre-link non dovrebbe mai eseguire manipolazioni DOM né eseguire una funzione di transclude, poiché il contenuto delle direttive figlio non è stato ancora collegato.

Per ogni direttiva, la sua funzione controller e pre-link viene eseguita prima della funzione controller e pre-link delle sue direttive figlio. Una volta completata la fase del controller e di pre-link per tutte le direttive, AngularJS inizia la fase di collegamento ed esegue le funzioni di post-link per ciascuna direttiva. La fase di collegamento viene eseguita in modo opposto ai flussi di esecuzione di compilazione, controller e pre-collegamento iniziando dai nodi DOM foglia e proseguendo fino al nodo DOM radice. L'attraversamento DOM post-link segue un percorso prevalentemente in profondità. Poiché ogni direttiva figlio è collegata, viene eseguita la sua funzione post-link.

La funzione post-link è la funzione più comunemente implementata nelle direttive AngularJS personalizzate. In questa funzione si può fare quasi tutto ciò che è ragionevole. Il DOM può essere manipolato (solo per se stesso e per gli elementi figlio), $scope è disponibile, è possibile utilizzare l'oggetto controller per le direttive padre, è possibile eseguire funzioni di transclude, ecc. Tuttavia, ci sono alcune limitazioni. Non è possibile aggiungere nuove direttive al DOM perché non verranno compilate. Inoltre, tutte le manipolazioni DOM devono essere eseguite utilizzando le funzioni DOM. Chiamare semplicemente la funzione html sull'elemento DOM e passare il nuovo HTML rimuoverà tutti i gestori di eventi aggiunti durante il processo di compilazione. Ad esempio, questi non funzioneranno come previsto:

 element.html(element.html());

o

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

Il codice non modificherà l'HTML, ma la riassegnazione della versione stringa degli elementi DOM rimuoverà tutti i gestori di eventi creati durante il processo di compilazione. Tipicamente, la funzione post-link viene utilizzata per collegare gestori di eventi, $watch es e $observe s.

Una volta eseguite tutte le funzioni di post-link, $scope viene applicato alla struttura DOM compilata e collegata e la pagina AngularJS prende vita.

Grafico della funzione direttiva

Di seguito è riportato un grafico che elenca lo scopo di ciascuna funzione, cosa è disponibile quando viene eseguita e le migliori pratiche su come utilizzare ciascuna funzione in modo appropriato.

Esecuzione
Ordine
Direttiva
Funzione
DOM Trascludi $ ambito Chiamabile
da Bambino
1 compilare Il DOM non è stato compilato ma il modello è stato caricato nell'area del contenuto dell'elemento DOM. Le direttive possono essere aggiunte e rimosse. DOM può essere manipolato sia con le funzioni DOM che con la sostituzione di stringhe HTML. La funzione Transclude è disponibile ma è obsoleta e non deve essere chiamata. Non disponibile. La funzione non può essere chiamata da elementi figlio.
2 controllore L'elemento DOM compilato è disponibile ma non deve essere modificato. Il contenuto figlio trascluso non è stato aggiunto all'elemento DOM. Non dovrebbero verificarsi modifiche al DOM perché questo è un controller e il contenuto figlio trascluso non è stato ancora collegato. La funzione Transclude è disponibile ma non deve essere chiamata. $scope è disponibile e può essere utilizzato. I parametri di funzione vengono iniettati utilizzando il servizio $injector . La funzione viene passata alle funzioni di collegamento delle direttive figlio ed è da esse richiamabile.
3 pre-collegamento L'elemento DOM compilato è disponibile ma non deve essere modificato perché gli elementi DOM della direttiva figlio non sono stati ancora collegati. La funzione Transclude è disponibile ma non deve essere chiamata. $scope è disponibile e può essere modificato. La funzione non è richiamabile dalle direttive figlio. Ma può chiamare i controllori delle direttive genitore.
4 post-link Sono disponibili l'elemento DOM compilato e gli elementi DOM della direttiva figlio. DOM può essere modificato solo con le funzioni DOM (nessuna sostituzione HTML) e possono essere aggiunti solo contenuti che non richiedono compilazione. Non è consentita l'aggiunta/rimozione di direttive. La funzione Transclude è disponibile e può essere chiamata. $scope è disponibile e può essere utilizzato. Non richiamabile dai figli delle direttive, ma può chiamare il controllore delle direttive padre.

Sommario

In questo tutorial sulle direttive AngularJS, abbiamo appreso lo scopo, l'ordine di esecuzione e le capacità e gli usi generali di ciascuna delle quattro funzioni della direttiva: compile , controller , pre-link e post-link . Delle quattro funzioni, controller e post-link sono le più comunemente utilizzate, ma per direttive più complesse che necessitano di un maggiore controllo del DOM o richiedono un ambiente di esecuzione con ambito privato è possibile utilizzare le funzioni di compilazione e pre-link.