Angular JS: Was braucht die Verknüpfungsfunktion der Direktive, als wir bereits den Controller der Direktive mit Gültigkeitsbereich hatten?

199

Ich muss einige Operationen am Bereich und an der Vorlage ausführen. Es scheint, dass ich das entweder in der linkFunktion oder in der controllerFunktion tun kann (da beide Zugriff auf den Bereich haben).

Wann ist es der Fall, wenn ich die linkFunktion und nicht den Controller verwenden muss?

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

Ich verstehe auch, dass dies linkdie nicht eckige Welt ist. Also kann ich verwenden $watch, $digestund $apply.

Welche Bedeutung hat die linkFunktion, als wir bereits einen Controller hatten?

Yugal Jindle
quelle
9
Was meinst du mit „ Außerdem verstehe ich , dass Link die Nicht-Winkel Welt ist. So kann ich $watch, $digestund $apply. “?
musikalisch_ut
2
Im Inneren sehen linkwir keine eckige Magie. dh keine 2-Wege-Bindungen usw. Nur dass wir die API des Winkels zur Verfügung haben.
Yugal Jindle

Antworten:

299

Nach meinem anfänglichen Kampf mit den linkund controllerFunktionen und dem Lesen einer Menge darüber denke ich, dass ich jetzt die Antwort habe.

Lassen Sie uns zuerst verstehen ,

Wie funktionieren Winkelanweisungen auf den Punkt gebracht:

  • Wir beginnen mit einer Vorlage (als Zeichenfolge oder in eine Zeichenfolge geladen)

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

  • Dies templateStringwird nun als eckiges Element gewickelt

    var el = angular.element(templateString);

  • Mit el, jetzt kompilieren wir es mit $compile, um die Link- Funktion zurück zu bekommen .

    var l = $compile(el)

    Folgendes passiert:

    • $compile geht die gesamte Vorlage durch und sammelt alle Anweisungen, die sie erkennt.
    • Alle entdeckten Direktiven werden rekursiv kompiliert und ihre linkFunktionen gesammelt.
    • Dann werden alle linkFunktionen in eine neue linkFunktion eingeschlossen und als zurückgegeben l.
  • Schließlich stellen wir scopedieser l(Link-) Funktion eine Funktion zur Verfügung , die die umschlossenen Link-Funktionen mit dieser scopeund ihren entsprechenden Elementen weiter ausführt .

    l(scope)

  • Dies fügt die templateals neuen Knoten in dem DOMund ruft controllerdie ihre Uhren zum fügt Umfang , die mit der Vorlage in DOM geteilt wird.

Geben Sie hier die Bildbeschreibung ein

Vergleich von compile vs link vs controller :

  • Jede Direktive wird nur einmal kompiliert und die Verknüpfungsfunktion bleibt zur Wiederverwendung erhalten. Wenn also etwas für alle Instanzen einer Direktive gilt, sollte dies innerhalb der compileFunktion der Direktive ausgeführt werden.

  • Nach der Kompilierung haben wir nun eine linkFunktion, die ausgeführt wird, während die Vorlage an das DOM angehängt wird . Deshalb führen wir alles aus, was für jede Instanz der Richtlinie spezifisch ist. Zum Beispiel: Anhängen von Ereignissen , Mutieren der Vorlage basierend auf dem Umfang usw.

  • Schließlich soll der Controller verfügbar sein, um live und reaktiv zu sein, während die Direktive am DOM(nach dem Anhängen) arbeitet. Deshalb:

    (1) Nach dem Einrichten der Ansicht [ V ] (dh Vorlage) mit Link. $scopeist unser [ M ] und $controllerist unser [ C ] in MVC

    (2) Nutzen Sie die 2-Wege- Bindung mit $ scope, indem Sie Uhren einrichten.

    (3) Es $scopewird erwartet, dass Uhren in der Steuerung hinzugefügt werden, da dies die Vorlage zur Laufzeit überwacht.

    (4) Schließlich controllerwird auch verwendet, um in der Lage zu sein, zwischen verwandten Richtlinien zu kommunizieren. (Wie myTabsBeispiel in https://docs.angularjs.org/guide/directive )

    (5) Es ist wahr, dass wir all dies auch in der linkFunktion hätten tun können, aber es geht um die Trennung von Bedenken .

Daher haben wir endlich folgendes, das perfekt zu allen Teilen passt:

Geben Sie hier die Bildbeschreibung ein

Yugal Jindle
quelle
5
Ich fand diesen Artikel auch nützlich, um die Reihenfolge der Ausführung hier zu verstehen: Das Wesentliche an Kompilierungs- und Verknüpfungsfunktionen in AngularJS-Direktiven
BobbyA
4
Tolle Erklärung. Ich möchte erwähnen, dass der Controller vor der Verbindungsfunktion aufgerufen wird.
Jsbisht
38
Controller wird vor dem Link ausgeführt
Royi Namir
10
Es macht mich wütend, dass Stack Overflow verlangt, dass die Änderungen mindestens 6 Zeichen umfassen, sodass ich die Schreibweise von Let's in dieser Antwort nicht korrigieren kann.
user1886323
79

Warum Controller benötigt werden

Der Unterschied zwischen linkund controllerkommt zum Tragen, wenn Sie Direktiven in Ihrem DOM verschachteln und API-Funktionen von der übergeordneten Direktive zu den verschachtelten verfügbar machen möchten.

Aus den Dokumenten :

Best Practice: Verwenden Sie Controller, wenn Sie eine API anderen Anweisungen aussetzen möchten. Andernfalls verwenden Sie den Link.

Angenommen, Sie möchten zwei Anweisungen haben my-formund my-text-inputmöchten, dass die my-text-inputAnweisung nur innerhalb my-formund nirgendwo anders angezeigt wird.

In diesem Fall sagen Sie beim Definieren der Direktive my-text-input, dass ein Controller aus dem parentDOM-Element erforderlich ist, indem Sie das Argument require wie folgt verwenden : require: '^myForm'. Nun wird der Controller vom übergeordneten Element als viertes Argument injectedin die linkFunktion aufgenommen $scope, element, attributes. Sie können Funktionen auf diesem Controller aufrufen und mit der übergeordneten Direktive kommunizieren.

Wenn ein solcher Controller nicht gefunden wird, wird außerdem ein Fehler ausgelöst.

Warum überhaupt Link verwenden

Es besteht keine wirkliche Notwendigkeit, die linkFunktion zu verwenden, wenn man die definiert, controllerda die $scopeauf der verfügbar ist controller. Während man beide linkund definiert controller, muss man außerdem auf die Reihenfolge des Aufrufs der beiden achten ( controllerwird vorher ausgeführt).

In Übereinstimmung mit der Angular-Methode werden die meisten DOM-Manipulationen und 2-Wege-Bindungen $watchersnormalerweise in der linkFunktion ausgeführt, während die API für untergeordnete Elemente und die $scopeManipulation in der Funktion ausgeführt werden controller. Dies ist keine feste Regel, aber dies macht den Code modularer und hilft bei der Trennung von Bedenken (der Controller behält den directiveStatus bei und die linkFunktion behält die DOM+ äußeren Bindungen bei).

musikalisch_ut
quelle
Das ist großartig. Können Sie mir jetzt beim zweiten Teil der Frage helfen?
Yugal Jindle
Ich meine, da wir den Controller hatten, der zur Kommunikation mit anderen Richtlinien hätte verwendet werden können. Also, was war die Notwendigkeit link?
Yugal Jindle
1
Ihre Antwort beantwortet irgendwie nicht die eigentliche Frage.
Yugal Jindle
1
Gibt es irgendwelche Probleme, die auftreten, wenn wir a definieren controller? Warum möchte ich eine ganz neue Funktion erfinden, um die Definition des Controllers zu vermeiden?
Yugal Jindle
1
es scheint, dass @scalaGirls Link nicht mehr funktioniert
Minato
17

Die controllerFunktion / das Objekt repräsentiert einen Abstraktionsmodell-View-Controller (MVC). Es gibt zwar nichts Neues über MVC zu schreiben, aber es ist immer noch der bedeutendste Vorteil von Angular: Teilen Sie die Bedenken in kleinere Teile auf. Und das ist es, nichts weiter. Wenn Sie also auf ModelÄnderungen reagieren müssen, die von Viewder kommen, Controllerist die richtige Person , um diesen Job zu erledigen.

Die Geschichte über die linkFunktion ist anders, sie kommt aus einer anderen Perspektive als MVC. Und ist wirklich wichtig, wenn wir die Grenzen einer controller/model/view (Vorlage) überschreiten wollen .

Beginnen wir mit den Parametern, die an die linkFunktion übergeben werden:

function link(scope, element, attrs) {
  • scope ist ein Angular-Scope-Objekt.
  • element ist das von jqLite umschlossene Element, mit dem diese Direktive übereinstimmt.
  • attrs ist ein Objekt mit den normalisierten Attributnamen und den entsprechenden Werten.

Um dies linkin den Kontext zu stellen, sollten wir erwähnen, dass alle Anweisungen diese Initialisierungsprozessschritte durchlaufen: Kompilieren , Verknüpfen . Ein Auszug aus Brad Green und Shyam Seshadri Buch Angular JS :

Kompilierungsphase (eine Schwester von Link, lassen Sie es uns hier erwähnen, um ein klares Bild zu erhalten):

In dieser Phase durchläuft Angular das DOM, um alle registrierten Anweisungen in der Vorlage zu identifizieren. Für jede Direktive transformiert es dann das DOM basierend auf den Regeln der Direktive (Vorlage, Ersetzen, Transkludieren usw.) und ruft die Kompilierungsfunktion auf, falls vorhanden. Das Ergebnis ist eine kompilierte Vorlagenfunktion.

Verbindungsphase :

Um die Ansicht dynamisch zu gestalten, führt Angular dann für jede Direktive eine Verknüpfungsfunktion aus. Die Verknüpfungsfunktionen erstellen normalerweise Listener im DOM oder im Modell. Diese Listener halten die Ansicht und das Modell jederzeit synchron.

Ein schönes Beispiel für die Verwendung von linkfinden Sie hier: Erstellen von benutzerdefinierten Anweisungen . Siehe Beispiel: Erstellen einer Direktive zum Manipulieren des DOM , bei der eine "Datum-Uhrzeit" in die Seite eingefügt wird, die jede Sekunde aktualisiert wird.

Nur ein sehr kurzer Ausschnitt aus dieser reichhaltigen Quelle oben, der die wahre Manipulation mit DOM zeigt. Der $ timeout-Dienst verfügt über eine Hook-Funktion und wird in seinem Destruktoraufruf gelöscht , um Speicherlecks zu vermeiden

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

 ...
Radim Köhler
quelle
3
Sie scheinen zu haben verglichen compilerund link. Die Frage ist, warum, linkals wir bereits hattencontroller
Yugal Jindle
Ich habe die Antwort erweitert, um sogar den Controller genauer zu beschreiben. Jetzt sollten die Konzepte des controllervs linkklarer sein ...
Radim Köhler
1
Ich kann mich mit dieser Erklärung zufrieden geben. Aber es scheint dort irgendwie verschwommen zu sein. Es wäre großartig, wenn jemand aus dem eckigen Team selbst dafür sprechen und projizieren könnte, wohin sie es sehen - zum linkoder zum controller.
Yugal Jindle
1
Das ist der einzige Teil, den ich verstehen möchte (Wann ist es nicht ausreichend?). Außerdem bekomme ich alle Vorteile von Angular In controllerund bin linkrelativ hässlich. Ein eckiges Team muss also einen guten Grund dafür haben, anstatt nur eine Option.
Yugal Jindle
1
Frage: Wenn der Controller nicht ausreicht? Antwort: Wenn Sie eine Erfahrung außerhalb von Angular benötigen, z. B. um ein JQuery-Plugin zu verwenden oder die JQlite-Funktion zu verwenden, wie im Dokument ( docs.angularjs.org/api/ng/function/angular.element :) erwähnt , benötigen Sie diese Link
Hasteq