Angular JS: Jaka jest potrzeba funkcji link dyrektywy, skoro mieliśmy już kontroler dyrektywy z zakresem?


199

Muszę wykonać pewne operacje na zakresie i szablonie. Wydaje się, że mogę to zrobić w linkfunkcji lub controllerfunkcji (ponieważ oba mają dostęp do zakresu).

Kiedy jest tak, że muszę korzystać z linkfunkcji, a nie ze sterownika?

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

Rozumiem również, że linkjest to świat nie kątowy. Więc mogę używać $watch, $digesti $apply.

Jakie znaczenie ma linkfunkcja, kiedy mieliśmy już kontroler?


9
Co masz na myśli przez „ Ponadto, rozumiem, że związek jest non-kanciasty świat. Tak, mogę używać $watch, $digesti $apply. ”?
— musically_ut

2
Wewnątrz linknie widzimy żadnej magii kątowej. tzn. brak powiązań dwukierunkowych itp. Wystarczy, że mamy dostępne api kątownika.
— Yugal Jindle

Odpowiedzi:


299

Po moim początkowym walka z linki controllerfunkcji czytania i sporo o nich, myślę, że teraz mam odpowiedź.

Najpierw zrozumiemy ,

Jak w skrócie działają dyrektywy kątowe:

  • Zaczynamy od szablonu (jako ciąg lub załadowany do ciągu)

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

  • Teraz templateStringjest to owinięte jako element kątowy

    var el = angular.element(templateString);

  • Dzięki el, teraz skompilować je $compileodzyskać łącza funkcję.

    var l = $compile(el)

    Oto co się dzieje

    • $compile przechodzi przez cały szablon i zbiera wszystkie rozpoznane dyrektywy.
    • Wszystkie wykryte dyrektywy są kompilowane rekurencyjnie, a ich linkfunkcje są gromadzone.
    • Następnie wszystkie linkfunkcje są pakowane w nową linkfunkcję i zwracane jako l.
  • Wreszcie, zapewniamy scopefunkcję tej funkcji l(link), która dodatkowo wykonuje zawinięte funkcje linku wraz z tą scopei odpowiadającymi jej elementami.

    l(scope)

  • Dodaje to templatejako nowy węzeł do DOMi wywołuje, controllerktóry dodaje swoje zegarki do zakresu współdzielonego z szablonem w DOM.

wprowadź opis zdjęcia tutaj

Porównanie kompilacji vs linku vs kontrolera :

  • Każda dyrektywa jest kompilowana tylko raz, a funkcja link zostaje zachowana do ponownego użycia. Dlatego jeśli coś dotyczy wszystkich instancji dyrektywy, należy ją wykonać w ramach compilefunkcji dyrektywy .

  • Teraz po kompilacji mamy linkfunkcję, która jest wykonywana podczas dołączania szablonu do DOM . Dlatego wykonujemy wszystko, co jest specyficzne dla każdej instancji dyrektywy. Na przykład: dołączanie zdarzeń , mutowanie szablonu na podstawie zakresu itp.

  • Wreszcie, kontroler ma być dostępny do działania i reagowania, podczas gdy dyrektywa działa na DOM(po przywiązaniu). W związku z tym:

    (1) Po skonfigurowaniu widoku [ V ] (tj. Szablonu) z linkiem. $scopejest naszym [ M ] i $controllernaszym [ C ] w MVC

    (2) Skorzystaj z 2-kierunkowego wiązania z $ scope , ustawiając zegarki.

    (3) $scopeoczekuje się, że zegarki zostaną dodane do kontrolera, ponieważ właśnie to ogląda szablon w czasie wykonywania.

    (4) Wreszcie, controllersłuży również do komunikowania się między powiązanymi dyrektywami. (Jak myTabsprzykład w https://docs.angularjs.org/guide/directive )

    (5) To prawda, że ​​moglibyśmy zrobić to wszystko również w linkfunkcji, ale chodzi o rozdzielenie obaw .

Dlatego wreszcie mamy następujące, które idealnie pasują do wszystkich elementów:

wprowadź opis zdjęcia tutaj


5
Uważam również, że ten artykuł jest przydatny do zrozumienia kolejności wykonywania tutaj: drobiazgowość funkcji kompilacji i łączenia w dyrektywach AngularJS
— BobbyA

4
Świetne wyjaśnienie. Chciałbym wspomnieć, że kontroler jest wywoływany przed funkcją link.
— jsbisht

38
kontroler jest wykonywany przed łączem
— Royi Namir,

10
Denerwuje mnie to, że Przepełnienie stosu wymaga, aby zmiany zawierały co najmniej 6 znaków, a tym samym nie pozwalają mi na poprawienie pisowni „Let's” w tej odpowiedzi.
— user1886323,

79

Dlaczego kontrolery są potrzebne

Różnica pomiędzy linki controllerpojawia się, gdy chcesz zagnieżdżać dyrektywy w DOM i wystawiać funkcje API z dyrektywy nadrzędnej na zagnieżdżone.

Z dokumentów :

Najlepsza praktyka: używaj kontrolera, gdy chcesz udostępnić API innym dyrektywom. W przeciwnym razie użyj linku.

Powiedz, że chcesz mieć dwie dyrektywy my-formi my-text-inputchcesz, aby my-text-inputdyrektywa pojawiła się tylko w środku my-formi nigdzie indziej.

W takim przypadku, można powiedzieć podczas definiowania dyrektywę my-text-inputże wymaga kontrolera z parentelementu DOM przy użyciu wymaga argumentu, tak: require: '^myForm'. Teraz kontroler z elementu nadrzędnego przejdzie injecteddo linkfunkcji jako czwarty argument za nim $scope, element, attributes. Możesz wywoływać funkcje na tym kontrolerze i komunikować się z dyrektywą nadrzędną.

Ponadto, jeśli taki kontroler nie zostanie znaleziony, zostanie zgłoszony błąd.

Po co w ogóle korzystać z linku

Nie ma potrzeby używania tej linkfunkcji, jeśli się ją definiuje, controllerponieważ $scopejest ona dostępna w controller. Ponadto, definiując jedno linki drugie controller, należy uważać na kolejność wywoływania dwóch ( controllerjest wykonywana wcześniej).

Jednak, zgodnie ze sposobem Angular , większość manipulacji DOM i 2-kierunkowe wiązanie $watchersodbywa się zwykle w linkfunkcji, podczas gdy API dla dzieci i $scopemanipulowanie odbywa się w controller. Nie jest to trudna i szybka reguła, ale spowoduje to, że kod będzie bardziej modułowy i pomoże w rozdzieleniu problemów (kontroler utrzyma directivestan, a linkfunkcja zachowa DOM+ powiązania zewnętrzne).


To wspaniale. Czy możesz mi pomóc w drugiej części pytania?
— Yugal Jindle

Mam na myśli, ponieważ mieliśmy kontroler, który mógłby zostać wykorzystany do komunikacji z innymi dyrektywami. Czego więc potrzebowaliśmy link?
— Yugal Jindle

1
Twoja odpowiedź w jakiś sposób nie odpowiada na rzeczywiste pytanie.
— Yugal Jindle

1
Czy występują jakieś problemy, gdy definiujemy controller? Dlaczego chcę wymyślić zupełnie nową funkcję, aby uniknąć definiowania kontrolera?
— Yugal Jindle

1
Wygląda na to, że link @scalaGirl s już nie działa
— Minato

17

controllerFunkcja / przedmiot stanowi abstrakcji modelu-view kontroler (MVC). Chociaż nie ma nic nowego do napisania o MVC, nadal jest to najważniejsza zaleta kąta: podziel obawy na mniejsze części. I to wszystko, nic więcej, więc jeśli trzeba reagować na Modelzmiany pochodzące z jest właściwa osoba zrobić to zadanie.ViewController

Historia o linkfunkcji jest inna, pochodzi z innej perspektywy niż MVC. Jest to naprawdę niezbędne, gdy chcemy przekroczyć granice controller/model/view (szablonu) .

Zacznijmy od parametrów, które są przekazywane do linkfunkcji:

function link(scope, element, attrs) {
  • zakres jest obiektem zakresu kątowego.
  • element to element zawinięty w jqLite, który jest zgodny z tą dyrektywą.
  • attrs to obiekt ze znormalizowanymi nazwami atrybutów i odpowiadającymi im wartościami.

Aby umieścić linkw kontekście, powinniśmy wspomnieć, że wszystkie dyrektywy przechodzą przez następujące kroki procesu inicjalizacji: Kompiluj , Łącz . Fragment książki Brada Greena i Shyama Seshadri Angular JS :

Faza kompilacji (siostra linku, wspomnijmy tutaj, aby uzyskać wyraźny obraz):

W tej fazie Angular prowadzi DOM w celu zidentyfikowania wszystkich zarejestrowanych dyrektyw w szablonie. Dla każdej dyrektywy następnie przekształca DOM w oparciu o reguły dyrektywy (szablon, zamień, przetaczaj itd.) I wywołuje funkcję kompilacji, jeśli istnieje. Wynikiem jest skompilowana funkcja szablonu,

Faza łącza :

Aby widok był dynamiczny, Angular uruchamia następnie funkcję link dla każdej dyrektywy. Funkcje łączenia zwykle tworzą detektory w DOM lub modelu. Słuchacze ci utrzymują synchronizację widoku i modelu.

Miły przykład korzystania z nich linkmożna znaleźć tutaj: Tworzenie niestandardowych dyrektyw . Zobacz przykład: Tworzenie dyrektywy, która manipuluje DOM , która wstawia na stronie „datę i godzinę”, odświeżana co sekundę.

Tylko bardzo krótki fragment z tego bogatego źródła powyżej, pokazujący prawdziwą manipulację za pomocą DOM. Istnieje funkcja przechwycona do usługi $ timeout, a także jest usuwana w wywołaniu destruktora, aby uniknąć wycieków pamięci

.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
Wygląda na to, że porównałeś compileri link. linkcontroller
— Pytają,

Rozszerzyłem odpowiedź, aby opisać nawet kontroler bardziej szczegółowo. Teraz koncepcje controllervs linkpowinny być jaśniejsze ...
— Radim Köhler,

1
Mogę poszukać wyjaśnienia. Ale wydaje się tam trochę rozmazane. Byłoby wspaniale, gdyby ktoś z samego zespołu kątowego mógł za to mówić, przewidując, dokąd go widzi - do linklub controller.
— Yugal Jindle

1
To jedyna część, którą chcę zrozumieć (kiedy to nie wystarczy?). Plus, mam wszystkie zalety kątowania controlleri linkjest względnie brzydki. Zespół Angular musi mieć ku temu dobry powód, a nie tylko opcję.
— Yugal Jindle

1
Pytanie: Kiedy kontroler jest niewystarczający? Odp .: Gdy potrzebujesz doświadczenia poza Angularem, takiego jak użycie wtyczki JQuery lub użycie funkcji JQlite, jak wspomniano w dokumencie ( docs.angularjs.org/api/ng/function/angular.element:) , wtedy potrzebujesz link
— Hasteq,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.