wake-up-neo.com

Angular JS: Was brauchte die Link-Funktion der Direktive, als wir bereits den Controller der Direktive mit Gültigkeitsbereich hatten?

Ich muss einige Vorgänge für den Bereich und die Vorlage ausführen. Es scheint, dass ich das entweder mit der Funktion link oder der Funktion controller tun kann (da beide Zugriff auf den Gültigkeitsbereich haben).

Wann ist es der Fall, wenn ich die Funktion link 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 link die nicht eckige Welt ist. Also kann ich $watch, $digest und $apply.

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

192
Yugal Jindle

Nach meinem anfänglichenKampf mit den link und controller Funktionen und dem Lesen einer Menge darüber, denke ich, habe ich jetzt die Antwort.

Zuerst lass verstehen,,

Wie funktionieren angular Direktiven auf den Punkt gebracht:

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

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

  • Nun wird dieses templateString als eckiges Elementumgebrochen.

    var el = angular.element(templateString);

  • Mit el kompilieren wir es jetzt mit $compile, Um die Funktion linkzurückzugewinnen.

    var l = $compile(el)

    Folgendes passiert,

    • $compile Durchläuft die gesamte Vorlage und sammelt alle erkannten Anweisungen.
    • Alle entdeckten Direktiven werden rekursiv kompiliertund ihre link -Funktionen werden gesammelt.
    • Dann werden alle link -Funktionen in eine neue link -Funktion eingeschlossen und als l zurückgegeben.
  • Schließlich stellen wir dieser Funktion scope die Funktion l (Verknüpfung) zur Verfügung, die die umbrochenen Verknüpfungsfunktionen mit dieser Funktion scope und den entsprechenden Elementen ausführt.

    l(scope)

  • Dies fügt den template als neuen Knoten zum DOM hinzu und ruft controller auf, der seine Überwachungen zum Bereichhinzufügt, der gemeinsam genutzt wird mit der Vorlage in DOM.

enter image description here

Vergleichen von compilevs linkvs controller:

  • Jede Direktive wird nur einmal kompiliert, und linkfunction wird zur Wiederverwendung beibehalten. Wenn also für alle Instanzen einer Direktive etwas zutrifft, sollte dies in der Funktion compile der Direktive ausgeführt werden.

  • Nach der Kompilierung haben wir nun die Funktion link, die ausgeführt wird, während das Templatean das [~ # ~] dom [~ # ~] angehängt wird.. Deshalb führen wir alles durch, was für jede Instanz der Direktive spezifisch ist. Zum Beispiel: Anhängen von Ereignissen, Mutieren der Vorlage basierend auf dem Gültigkeitsbereichusw.

  • Schließlich soll der Controllerverfügbar sein, um live und reaktiv zu sein, während die Direktive auf dem DOM arbeitet (nachdem sie angehängt wurde). Deshalb:

    (1) Nach dem Einrichten der Ansicht [ [~ # ~] v [~ # ~]] (d. H. Vorlage) mit Link. $scope Ist unser [ [~ # ~] m [~ # ~]] und $controller Ist unser [ [~ # ~] c [~ # ~]] in MVC

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

    (3) Es wird erwartet, dass $scope - Uhren im Controller hinzugefügt werden, da dies das ist, was die Vorlage während der Laufzeit überwacht.

    (4) Schließlich wird controller auch verwendet, um zwischen verwandten Anweisungen kommunizieren zu können. (Wie myTabs Beispiel in https://docs.angularjs.org/guide/directive )

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

Deshalb haben wir endlich das Folgende, das perfekt zu allen Teilen passt:

enter image description here

291
Yugal Jindle

Warum Controller benötigt werden

Der Unterschied zwischen link und controller kommt zum Tragen, wenn Sie Anweisungen in Ihrem DOM verschachteln und API-Funktionen aus der übergeordneten Anweisung für die verschachtelten verfügbar machen möchten.

Aus dem docs :

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

Angenommen, Sie möchten zwei Anweisungen haben my-form und my-text-input und du willst my-text-input Direktive erscheint nur in my-form und nirgendwo anders.

In diesem Fall werden Sie beim Definieren der Direktive my-text-input dass es einen Controller aus dem DOM-Element parent unter Verwendung des Arguments require erfordert =, wie folgt: require: '^myForm'. Nun wird der Controller aus dem übergeordneten Element injected in die Funktion link als viertes Argument nach $scope, element, attributes. Sie können Funktionen auf diesem Controller aufrufen und mit der übergeordneten Direktive kommunizieren.

Darüber hinaus wird ein Fehler ausgelöst, wenn ein solcher Controller nicht gefunden wird.

Warum überhaupt einen Link benutzen?

Es besteht keine wirkliche Notwendigkeit, die Funktion link zu verwenden, wenn man die Funktion controller definiert, seitdem $scope ist auf dem controller verfügbar. Außerdem muss man beim Definieren von link und controller auf die Reihenfolge des Aufrufs der beiden achten (controller wird zuvor ausgeführt).

In Übereinstimmung mit dem Angular Way werden jedoch die meisten DOM-Manipulationen und 2-Wege-Bindungen mit $watchers wird normalerweise in der Funktion link ausgeführt, während die API für Kinder und $scope Die Bearbeitung erfolgt in controller. Dies ist keine harte und schnelle Regel, aber dadurch wird der Code modularer und hilft bei der Trennung von Bedenken (der Controller behält den directive -Status bei und die link -Funktion behält den DOM + Außenbindungen).

72
musically_ut

Die controller Funktion/Objekt repräsentiert einen Abstraction Model-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 wars auch schon, also wenn Sie auf Model Änderungen reagieren müssen, die von View kommen, ist Controller die richtige Person mach diesen Job.

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

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

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

Um link in den Kontext zu setzen, sollten wir erwähnen, dass alle Direktiven diese Schritte des Initialisierungsprozesses durchlaufen: Compile, Link. Ein Auszug aus Brad Green und Shyam Seshadri Buch Angular JS:

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

In dieser Phase durchsucht Angular das DOM, um alle registrierten Anweisungen in der Vorlage zu identifizieren. Für jede Anweisung wird das DOM dann basierend auf den Richtlinienregeln (Vorlage, Ersetzen, transclude und so weiter) und ruft die Kompilierungsfunktion auf, falls vorhanden. Das Ergebnis ist eine kompilierte Vorlagenfunktion,

Verbindungsphase :

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

Ein gutes Beispiel für die Verwendung von link finden Sie hier: Create Custom Directives . Siehe das Beispiel: Erstellen einer Direktive, die das DOM manipuliert , wobei eine "Datum-Zeit" in eine Seite eingefügt wird, die jede Sekunde aktualisiert wird.

Nur ein sehr kurzer Ausschnitt aus dieser reichen Quelle, der die reale Manipulation mit DOM zeigt. Es gibt eine Hook-Funktion für $ timeout service und sie wird auch in ihrem Aufruf destructor gelöscht, um Speicherverluste 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);
 });

 ...
17
Radim Köhler