angularjs - update - angular set page title from controller




Angular Direktiven-wann und wie man compile, controller, pre-link und post-link verwendet (6)

Controller-Funktion

Die controller jeder Anweisung wird aufgerufen, wenn ein neues verwandtes Element instanziiert wird.

Offiziell ist die controller Funktion, wo man:

  • Definiert die Steuerungslogik (Methoden), die von den Steuerungen gemeinsam genutzt werden können.
  • Initiiert Bereichsvariablen.

Auch hier ist es wichtig, sich daran zu erinnern, dass, wenn die Richtlinie einen isolierten Gültigkeitsbereich umfasst, noch keine Eigenschaften vorhanden sind, die vom übergeordneten Gültigkeitsbereich erben.

Machen:

  • Definieren Sie die Steuerungslogik
  • Initiiere Bereichsvariablen

Unterlassen Sie:

  • Untergeordnete Elemente überprüfen (sie werden möglicherweise noch nicht gerendert, sind an den Bereich gebunden usw.).

Wenn Sie eine Angular-Direktive schreiben, können Sie eine der folgenden Funktionen verwenden, um das DOM-Verhalten, den Inhalt und das Aussehen des Elements zu beeinflussen, für das die Direktive deklariert ist:

  • kompilieren
  • Regler
  • Vorlink
  • Post-Link

Es scheint einige Verwirrung darüber zu geben, welche Funktion man verwenden sollte. Diese Frage umfasst:

Grundlagen der Richtlinie

  • Wie deklarieren Sie die verschiedenen Funktionen?
  • Was ist der Unterschied zwischen einer Quellvorlage und einer Instanzvorlage ?
  • In welcher Reihenfolge werden die Anweisungsfunktionen ausgeführt?
  • Was passiert noch zwischen diesen Funktionsaufrufen?

Funktion Natur, Do's und Dont's

  • Compile
  • Controller
  • Pre-link
  • Post-link

Verwandte Fragen:


In welcher Reihenfolge werden die Anweisungsfunktionen ausgeführt?

Für eine einzelne Richtlinie

Berücksichtigen Sie anhand des folgenden plunk das folgende HTML-Markup:

<body>
    <div log='some-div'></div>
</body>

Mit der folgenden Direktivenerklärung:

myApp.directive('log', function() {

    return {
        controller: function( $scope, $element, $attrs, $transclude ) {
            console.log( $attrs.log + ' (controller)' );
        },
        compile: function compile( tElement, tAttributes ) {
            console.log( tAttributes.log + ' (compile)'  );
            return {
                pre: function preLink( scope, element, attributes ) {
                    console.log( attributes.log + ' (pre-link)'  );
                },
                post: function postLink( scope, element, attributes ) {
                    console.log( attributes.log + ' (post-link)'  );
                }
            };
         }
     };  

});

Die Konsolenausgabe wird sein:

some-div (compile)
some-div (controller)
some-div (pre-link)
some-div (post-link)

Wir können sehen, dass compile zuerst ausgeführt wird, dann controller , dann pre-link und zuletzt ist post-link .

Für verschachtelte Anweisungen

Hinweis: Folgendes trifft nicht auf Anweisungen zu, die ihre untergeordneten Elemente in ihrer Verknüpfungsfunktion rendern. Einige Angular-Direktiven tun dies (wie ngIf, ngRepeat oder irgendeine Direktive mit transclude ). Diese Direktiven werden nativ ihre link aufrufen, bevor ihre untergeordneten Anweisungen compile .

Das ursprüngliche HTML-Markup besteht häufig aus verschachtelten Elementen mit jeweils eigenen Anweisungen. Wie im folgenden Markup (siehe plunk ):

<body>
    <div log='parent'>
        <div log='..first-child'></div>
        <div log='..second-child'></div>
    </div>
</body>

Die Konsolenausgabe sieht folgendermaßen aus:

// The compile phase
parent (compile)
..first-child (compile)
..second-child (compile)

// The link phase   
parent (controller)
parent (pre-link)
..first-child (controller)
..first-child (pre-link)
..first-child (post-link)
..second-child (controller)
..second-child (pre-link)
..second-child (post-link)
parent (post-link)

Wir können hier zwei Phasen unterscheiden - die Compile- Phase und die Link- Phase.

Die Kompilierphase

Wenn das DOM geladen wird, startet Angular die Kompilierphase, wo es das Markup von oben nach unten durchläuft und Aufrufe für alle Direktiven compile . Grafisch könnten wir es so ausdrücken:

Es ist vielleicht wichtig zu erwähnen, dass die Templates, die die Kompilierfunktion in diesem Stadium erhält, die Quellvorlagen sind (keine Instanzschablonen).

Die Verbindungsphase

DOM-Instanzen sind oft einfach das Ergebnis einer Quellvorlage, die für das DOM gerendert wird, aber sie können durch ng-repeat oder im laufenden Betrieb eingeführt werden.

Immer wenn eine neue Instanz eines Elements mit einer Direktive für das DOM gerendert wird, beginnt die Link-Phase.

In dieser Phase ruft Angular den controller , pre-link , iteriert untergeordnete Elemente und ruft post-link für alle Direktiven auf:


Post-Link-Funktion

Wenn die post-link Funktion aufgerufen wird, haben alle vorherigen Schritte stattgefunden - Bindung, Transclusion usw.

Dies ist normalerweise ein Platz, um das gerenderte DOM weiter zu manipulieren.

Machen:

  • Bearbeiten Sie DOM-Elemente (gerendert und damit instanziiert).
  • Hängen Sie Ereignishandler an.
  • Untergeordnete Elemente prüfen.
  • Richten Sie Beobachtungen zu Attributen ein.
  • Richten Sie am Scope Uhren ein.

Pre-Link-Funktion

Die pre-link Funktion jeder Direktive wird aufgerufen, wenn ein neues verwandtes Element instanziiert wird.

Wie zuvor im Abschnitt zur Kompilierungsreihenfolge zu sehen ist, werden pre-link Funktionen als Parent-Then-Child bezeichnet, während post-link Funktionen child-then-parent .

Die pre-link Funktion wird selten verwendet, kann aber in speziellen Szenarien nützlich sein. Wenn sich ein untergeordneter Controller zum Beispiel beim übergeordneten Controller ngModelController muss die Registrierung in einer parent-then-child ngModelController ( ngModelController führt dies auf diese Weise aus).

Unterlassen Sie:

  • Untergeordnete Elemente überprüfen (sie werden möglicherweise noch nicht gerendert, sind an den Bereich gebunden usw.).

Was passiert noch zwischen diesen Funktionsaufrufen?

Die verschiedenen Anweisungsfunktionen werden innerhalb von zwei anderen Winkelfunktionen ausgeführt, die $compile (wo die $compile der Direktive ausgeführt wird) und eine interne Funktion, die nodeLinkFn heißt (wobei der controller der controller , preLink und postLink ausgeführt werden). Innerhalb der Winkelfunktion passieren verschiedene Dinge, bevor und nachdem die Anweisungsfunktionen aufgerufen werden. Vielleicht am bemerkenswertesten ist die Kinderrekursion. Die folgende vereinfachte Abbildung zeigt die wichtigsten Schritte innerhalb der Kompilierungs- und Link-Phasen:

Um diese Schritte zu demonstrieren, verwenden wir das folgende HTML-Markup:

<div ng-repeat="i in [0,1,2]">
    <my-element>
        <div>Inner content</div>
    </my-element>
</div>

Mit der folgenden Richtlinie:

myApp.directive( 'myElement', function() {
    return {
        restrict:   'EA',
        transclude: true,
        template:   '<div>{{label}}<div ng-transclude></div></div>'
    }
});

Kompilieren

Die compile API sieht folgendermaßen aus:

compile: function compile( tElement, tAttributes ) { ... }

Häufig wird den Parametern ein Präfix mit t vorangestellt, um zu signalisieren, dass die bereitgestellten Elemente und Attribute denen der Quellenvorlage und nicht der der Instanz entsprechen.

Vor dem Aufruf compile Inhalte (falls vorhanden) wird entfernt und die Vorlage wird auf das Markup angewendet. Das für die compile bereitgestellte Element sieht also folgendermaßen aus:

<my-element>
    <div>
        "{{label}}"
        <div ng-transclude></div>
    </div>
</my-element>

Beachten Sie, dass der übertragene Inhalt zu diesem Zeitpunkt nicht erneut eingefügt wird.

Nach dem Aufruf der .compile Anweisung der .compile wird Angular alle .compile Elemente durchlaufen, einschließlich derjenigen, die möglicherweise gerade von der Richtlinie eingeführt wurden (z. B. die Vorlagenelemente).

Instanzerstellung

In unserem Fall werden drei Instanzen der obigen Quellenvorlage erstellt (durch ng-repeat ). Somit wird die folgende Sequenz dreimal pro Instanz ausgeführt.

Regler

Die controller API umfasst Folgendes:

controller: function( $scope, $element, $attrs, $transclude ) { ... }

In der Link-Phase wird nun die über $compile Link-Funktion mit einem Bereich versehen.

Zuerst erstellt die Verknüpfungsfunktion auf Anforderung einen untergeordneten Bereich ( scope: true ) oder einen isolierten Bereich ( scope: {...} ).

Der Controller wird dann ausgeführt und mit dem Bereich des Instanzelements versehen.

Vorlink

Die pre-link API sieht folgendermaßen aus:

function preLink( scope, element, attributes, controller ) { ... }

Praktisch nichts passiert zwischen dem Aufruf des .controller der Direktive und der Funktion .preLink . Angular gibt immer noch Empfehlungen, wie jeder verwendet werden sollte.

Nach dem Aufruf .preLink die Verknüpfungsfunktion jedes .preLink Element - ruft die richtige Verknüpfungsfunktion auf und fügt den aktuellen Bereich an (der als übergeordneter Bereich für untergeordnete Elemente dient).

Postlink

Die post-link API ähnelt der der pre-link Funktion:

function postLink( scope, element, attributes, controller ) { ... }

Vielleicht ist es bemerkenswert, dass sobald die Funktion .postLink einer Anweisung .postLink wird, der Link-Prozess aller seiner .postLink Elemente abgeschlossen ist, einschließlich aller .postLink Funktionen der Kinder.

Das bedeutet, dass zu dem Zeitpunkt, an dem .postLink aufgerufen wird, die Kinder "live" bereit sind. Das beinhaltet:

  • Datenbindung
  • Transklusion angewendet
  • Umfang beigefügt

Die Vorlage in diesem Stadium sieht also so aus:

<my-element>
    <div class="ng-binding">
        "{{label}}"
        <div ng-transclude>                
            <div class="ng-scope">Inner content</div>
        </div>
    </div>
</my-element>

Wie deklarieren Sie die verschiedenen Funktionen?

Kompilieren, Controller, Pre-Link & Post-Link

Wenn man alle vier Funktionen verwenden möchte, folgt die Direktive dieser Form:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.
            return {
                pre: function preLink( scope, element, attributes, controller, transcludeFn ) {
                    // Pre-link code goes here
                },
                post: function postLink( scope, element, attributes, controller, transcludeFn ) {
                    // Post-link code goes here
                }
            };
        }
    };  
});

Beachten Sie, dass die Kompilierung ein Objekt zurückgibt, das sowohl die Pre-Link- als auch die Post-Link-Funktionen enthält. Im Angular-Jargon sagen wir, dass die Kompilierfunktion eine Template-Funktion zurückgibt.

Kompilieren, Controller & Post-Link

Wenn pre-link nicht erforderlich ist, kann die Compilerfunktion einfach die Post-Link-Funktion anstelle eines Definitionsobjekts wie folgt zurückgeben:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.
            return function postLink( scope, element, attributes, controller, transcludeFn ) {
                    // Post-link code goes here                 
            };
        }
    };  
});

Manchmal möchte man eine compile hinzufügen, nachdem die (Post-) link Methode definiert wurde. Dazu kann man verwenden:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.

            return this.link;
        },
        link: function( scope, element, attributes, controller, transcludeFn ) {
            // Post-link code goes here
        }

    };  
});

Controller & Post-Link

Wenn keine Kompilierfunktion benötigt wird, kann die Deklaration komplett übersprungen werden und die Post-Link-Funktion unter der Eigenschaft link des Konfigurationsobjekts der Direktive bereitgestellt werden:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        link: function postLink( scope, element, attributes, controller, transcludeFn ) {
                // Post-link code goes here                 
        },          
    };  
});

Kein Controller

In jedem der obigen Beispiele kann man die controller Funktion einfach entfernen, wenn sie nicht benötigt wird. Wenn zum Beispiel nur die post-link Funktion benötigt wird, kann man verwenden:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        link: function postLink( scope, element, attributes, controller, transcludeFn ) {
                // Post-link code goes here                 
        },          
    };  
});






angularjs-directive