Samouczek AngularJS: wyjaśnianie dyrektyw niestandardowych

Opublikowany: 2022-03-11

Wraz z szybkim rozwojem JavaScript jako języka pełnego stosu, coraz więcej aplikacji wykorzystuje frameworki, które umożliwiają przeglądarce internetowej obsłużenie większej liczby procesów interfejsu użytkownika, takich jak wiązanie danych, zarządzanie widokami danych, przekształcanie danych i wiele innych usług. Jednym z najbardziej wydajnych, rozszerzalnych i popularnych frameworków jest AngularJS, a jednym z najbardziej użytecznych komponentów frameworka AngularJS jest coś, co nazywa się dyrektywą . AngularJS dostarcza wiele przydatnych dyrektyw i, co ważniejsze, zapewnia bogaty framework do tworzenia niestandardowych dyrektyw.

Czym jest dyrektywa? Mówiąc prościej, dyrektywy to funkcje JavaScript, które manipulują i dodają zachowania do elementów HTML DOM. Dyrektywy mogą być bardzo uproszczone lub niezwykle skomplikowane. Dlatego zdobycie solidnego zrozumienia ich wielu opcji i funkcji, które nimi manipulują, ma kluczowe znaczenie.

W tym samouczku zostaną zbadane cztery funkcje, które są wykonywane jako dyrektywa, i zastosowane do DOM, a przykłady zostaną dostarczone. Ten post zakłada pewną znajomość dyrektyw AngularJS i niestandardowych. Jeśli jesteś nowszy w Angular, możesz skorzystać z samouczka na temat tworzenia pierwszej aplikacji AngularJS.

Cztery funkcje cyklu życia dyrektywy AngularJS

Istnieje wiele opcji, które można skonfigurować, a to, jak te opcje są ze sobą powiązane, jest ważne. Każda dyrektywa przechodzi coś podobnego do cyklu życia, gdy AngularJS kompiluje i łączy DOM. Cykl życia dyrektywy rozpoczyna się i kończy w procesie ładowania początkowego AngularJS, zanim strona zostanie wyrenderowana. W cyklu życia dyrektywy istnieją cztery różne funkcje, które mogą być wykonywane, jeśli są zdefiniowane. Każda z nich umożliwia programiście kontrolowanie i dostosowywanie dyrektywy w różnych punktach cyklu życia.

Te cztery funkcje to: kompilacja , kontroler , pre-link i post-link .

Funkcja kompilacji pozwala dyrektywie na manipulowanie DOM przed jego skompilowaniem i połączeniem, co pozwala na dodawanie/usuwanie/zmianę dyrektyw, jak również dodawanie/usuwanie/zmianę innych elementów DOM.

Funkcja sterownika ułatwia komunikację dyrektyw. Dyrektywy dotyczące rodzeństwa i dzieci mogą wymagać od kontrolera ich rodzeństwa i rodziców przekazania informacji.

Funkcja pre-link pozwala na prywatną manipulację $scope przed rozpoczęciem procesu post-link.

Metoda post-link to podstawowa metoda „konia roboczego” dyrektywy.

W dyrektywie ma miejsce manipulacja DOM po kompilacji, konfigurowane są programy obsługi zdarzeń, zegarki i inne rzeczy. W deklaracji dyrektywy cztery funkcje są zdefiniowane w ten sposób.

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

Zwykle nie wszystkie funkcje są potrzebne. W większości przypadków programiści po prostu utworzą kontroler i funkcję post-link zgodnie z poniższym wzorem.

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

W tej konfiguracji link odnosi się do funkcji post-link .

Niezależnie od tego, czy zdefiniowane są wszystkie, czy niektóre funkcje, ważna jest kolejność ich wykonywania, zwłaszcza ich wykonanie w stosunku do reszty aplikacji AngularJS.

Dyrektywa AngularJS Wykonanie funkcji względem innych dyrektyw

Rozważmy następujący fragment kodu HTML z dyrektywami parentDir , childDir i grandChildDir zastosowanymi do fragmentu HTML.

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

Kolejność wykonywania funkcji w ramach dyrektywy i względem innych dyrektyw jest następująca:

  • Faza kompilacji
    • Funkcja kompilacji : parentDir
    • Funkcja kompilacji : childDir
    • Funkcja kompilacji : grandChildDir
  • Kontroler i faza przed połączeniem
    • Funkcja kontrolera : parentDir
    • Funkcja wstępnego połączenia : parentDir
    • Funkcja kontrolera : childDir
    • Funkcja Pre-Link : childDir
    • Funkcja kontrolera : grandChildDir
    • Funkcja Pre-Link : grandChildDir
  • Faza post-link
    • Funkcja post-Link : grandChildDir
    • Funkcja Post-Link : childDir
    • Funkcja post-link : parentDir

Samouczek funkcji dyrektywy AngularJS - kolejność wykonywania względem innych dyrektyw.

Objaśnienie funkcji dyrektywy AngularJS: głębokie nurkowanie

Faza kompilacji następuje jako pierwsza. Zasadniczo faza kompilacji dołącza detektory zdarzeń do elementów DOM. Na przykład, jeśli określony element DOM jest powiązany z właściwością $scope , detektor zdarzeń, który umożliwia jego aktualizację o wartość właściwości $scope , jest stosowany do elementu DOM. Proces kompilacji rozpoczyna się od głównego elementu DOM, z którego została załadowana aplikacja AngularJS i przechodzi w dół gałęzi DOM przy użyciu przechodzenia w głąb, najpierw kompilując rodzica, a następnie jego dzieci, aż do węzłów liścia.

Po zakończeniu kompilacji dyrektyw nie można już dodawać ani usuwać z DOM (chociaż można to obejść, korzystając bezpośrednio z usługi kompilacji. Następna faza to wywoływanie kontrolerów i funkcji pre-link dla wszystkich dyrektyw. Kiedy kontroler $scope jest dostępny i może być użyty. Element $ wstrzyknięty do kontrolera zawiera skompilowany szablon, ale nie zawiera transkludowanej treści podrzędnej (transcludowana treść to treść między początkowymi i końcowymi znacznikami HTML, na których znajduje się dyrektywa Z definicji kontrolery we wzorcu MVC po prostu przekazują model do widoku i definiują funkcje do obsługi zdarzeń. Dlatego kontroler dyrektywy nie powinien modyfikować DOM dyrektywy z dwóch powodów: narusza to cel kontrolera, a transkludowana zawartość podrzędna nie została dodana do DOM. Więc co kontroler robi poza modyfikacją $scope ? Kontroler pozwala dyrektywom podrzędnym komunikować się z dyrektywy nadrzędne. Sama funkcja kontrolera powinna być traktowana jako obiekt kontrolera, który zostanie przekazany do funkcji post-link dyrektywy potomnej, jeśli dyrektywa potomna tego zażąda. Dlatego kontroler jest zwykle używany do ułatwienia komunikacji dyrektyw poprzez utworzenie obiektu z właściwościami i metodami, które mogą być używane przez jego dyrektywy siostrzane i podrzędne. Dyrektywa nadrzędna nie może określić, czy dyrektywa podrzędna może wymagać swojego kontrolera, dlatego najlepiej jest ograniczyć kod w tej metodzie do funkcji i właściwości, które mogą być bezpiecznie używane przez dyrektywy podrzędne.

Po funkcji kontrolera wykonywana jest funkcja pre-link. Funkcja wstępnego łączenia jest dla wielu osób tajemnicza. Jeśli czytasz dużo dokumentacji w Internecie iw książkach, ludzie piszą, że ta funkcja jest używana tylko w rzadkich przypadkach i ludzie prawie nigdy jej nie będą potrzebować. Te same wyjaśnienia nie dają wtedy przykładu sytuacji, w której można by go użyć.

Funkcja pre-link naprawdę wcale nie jest skomplikowana. Po pierwsze, jeśli przejrzysz kod źródłowy AngularJS, znajdziesz doskonały przykład funkcji pre-link: używa jej dyrektywa ng-init . Czemu? Jest to po prostu świetna metoda na wykonanie prywatnego kodu obejmującego $scope ; kod, który nie może być wywołany przez dyrektywy rodzeństwa i dzieci. W przeciwieństwie do funkcji kontrolera, funkcja pre-link nie jest przekazywana do dyrektyw. Dlatego może być użyty do wykonania kodu, który modyfikuje $scope swojej dyrektywy. Dyrektywa ng-init robi dokładnie to. Kiedy wykonywana jest funkcja pre-link dla ng-init , po prostu wykonuje JavaScript przekazany do dyrektywy przeciwko $scope dyrektywy. Wynik wykonania jest dostępny poprzez prototypowe dziedziczenie $scope do dyrektyw podrzędnych podczas ich kontrolera, wykonywania funkcji przed łączem i po łączeniu, ale bez udzielania dostępu do tych dyrektyw podrzędnych w celu ponownego wykonania kodu w funkcja łącza. Ponadto dyrektywa może wymagać wykonania innego kodu niezwiązanego z zakresem $scope , który chce zachować jako prywatny.

Niektórzy doświadczeni programiści AngularJS powiedzieliby, że ten prywatny kod nadal może być umieszczony w kontrolerze, a następnie nie będzie wywoływany przez dyrektywy potomne. Argument ten byłby prawdziwy, gdyby dyrektywa była używana tylko przez pierwotnego programistę, który ją zakodował, ale jeżeli dyrektywa ma być rozpowszechniana i ponownie wykorzystywana przez innych programistów, wówczas enkapsulacja prywatnego kodu w funkcji pre-link może być bardzo korzystna. Ponieważ programiści nigdy nie wiedzą, w jaki sposób ich dyrektywa zostanie ponownie wykorzystana z biegiem czasu, ochrona prywatnego kodu przed wykonaniem przez dyrektywę podrzędną jest dobrym podejściem do enkapsulacji kodu dyrektywy. Uważam, że dobrą praktyką jest umieszczenie publicznego kodu komunikacji dyrektywy w funkcji kontrolera, a kodu prywatnego w funkcji pre-link. Podobnie jak kontroler, prelink nigdy nie powinien wykonywać manipulacji DOM ani wykonywać funkcji transclude, ponieważ zawartość dyrektyw podrzędnych nie została jeszcze połączona.

W przypadku każdej dyrektywy jej kontroler i funkcja wstępnego łączenia są wykonywane przed kontrolerem i funkcją wstępnego łączenia jej dyrektyw podrzędnych. Po zakończeniu fazy kontrolera i pre-link dla wszystkich dyrektyw, AngularJS rozpoczyna fazę łączenia i wykonuje funkcje post-link dla każdej dyrektywy. Faza łączenia przebiega przeciwnie do przepływów kompilacji, kontrolera i wykonywania pre-link, zaczynając od węzłów liścia DOM i przechodząc do głównego węzła DOM. Przemierzanie DOM post-link podąża głównie ścieżką w głąb. Ponieważ każda dyrektywa potomna jest łączona, wykonywana jest jej funkcja post-link.

Funkcja post-link jest funkcją najczęściej implementowaną w niestandardowych dyrektywach AngularJS. W tej funkcji można zrobić prawie wszystko, co rozsądne. DOM można manipulować (tylko dla siebie i elementów potomnych), dostępny jest $scope , można użyć obiektu kontrolera dla dyrektyw nadrzędnych, można uruchomić funkcje transclude itp. Istnieje jednak kilka ograniczeń. Nie można dodawać nowych dyrektyw do DOM, ponieważ nie zostaną one skompilowane. Dodatkowo wszystkie manipulacje DOM muszą być wykonywane przy użyciu funkcji DOM. Proste wywołanie funkcji html na elemencie DOM i przekazanie nowego kodu HTML usunie wszystkie procedury obsługi zdarzeń dodane podczas procesu kompilacji. Na przykład te nie będą działać zgodnie z oczekiwaniami:

 element.html(element.html());

lub

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

Kod nie spowoduje zmiany kodu HTML, ale ponowne przypisanie wersji łańcuchowej elementów DOM usunie wszystkie procedury obsługi zdarzeń utworzone podczas procesu kompilacji. Zazwyczaj funkcja post-link jest używana do łączenia programów obsługi zdarzeń, $watch i $observe s.

Po wykonaniu wszystkich funkcji post-link, $scope jest stosowany do skompilowanej i połączonej struktury DOM, a strona AngularJS ożywa.

Tabela funkcji dyrektywy

Oto wykres przedstawiający przeznaczenie każdej funkcji, dostępne informacje po jej wykonaniu oraz najlepsze praktyki dotyczące prawidłowego korzystania z każdej funkcji.

Wykonanie
Zamówienie
Dyrektywa
Funkcjonować
DOM Transkluzja $zakres Można zadzwonić
przez dziecko
1 skompilować DOM nie został skompilowany, ale szablon został załadowany do obszaru zawartości elementu DOM. Dyrektywy można dodawać i usuwać. DOM można manipulować zarówno za pomocą funkcji DOM, jak i zastępowania ciągów HTML. Funkcja transclude jest dostępna, ale jest przestarzała i nie należy jej wywoływać. Niedostępne. Funkcja nie może być wywołana przez elementy podrzędne.
2 kontroler Skompilowany element DOM jest dostępny, ale nie należy go modyfikować. Transkludowana treść podrzędna nie została dodana do elementu DOM. Nie powinny wystąpić żadne zmiany DOM, ponieważ jest to kontroler, a transkludowana zawartość podrzędna nie została jeszcze połączona. Funkcja transkluzji jest dostępna, ale nie należy jej wywoływać. $scope jest dostępny i może być używany. Parametry funkcji są wstrzykiwane za pomocą usługi $injector . Funkcja jest przekazywana do dyrektywy podrzędnej łączącej funkcje i jest przez nie wywoływana.
3 wstępny link Skompilowany element DOM jest dostępny, ale nie należy go modyfikować, ponieważ elementy DOM dyrektywy podrzędnej nie zostały jeszcze połączone. Funkcja transkluzji jest dostępna, ale nie należy jej wywoływać. $scope jest dostępny i można go modyfikować. Funkcja nie jest wywoływana przez dyrektywy podrzędne. Ale może wywołać kontrolery dyrektyw nadrzędnych.
4 post-link Dostępne są skompilowany element DOM i elementy DOM dyrektywy podrzędnej. DOM można modyfikować tylko za pomocą funkcji DOM (bez zastępowania HTML) i można dodawać tylko zawartość, która nie wymaga kompilacji. Niedozwolone jest dodawanie/usuwanie dyrektyw. Funkcja transkluzji jest dostępna i można ją wywołać. $scope jest dostępny i może być używany. Nie można wywoływać przez dyrektywy potomne, ale może wywoływać kontroler dyrektyw nadrzędnych.

Streszczenie

W tym samouczku dotyczącym dyrektyw AngularJS poznaliśmy cel, kolejność wykonywania oraz ogólne możliwości i zastosowania każdej z czterech funkcji dyrektyw: compile , controller , pre-link i post-link . Spośród tych czterech funkcji najczęściej używane są kontroler i post-link, ale w przypadku bardziej złożonych dyrektyw, które wymagają większej kontroli nad DOM lub środowiska wykonawczego o zakresie prywatnym, można wykorzystać funkcje kompilacji i pre-link.