Direktiven sind eine der leistungsfähigsten Komponenten von AngularJS und helfen Ihnen, grundlegende HTML-Elemente / -Attribute zu erweitern und zu erstellen wiederverwendbar und überprüfbar Code. In diesem Tutorial werde ich Ihnen zeigen, wie Sie die AngularJS-Direktiven mit bewährten Vorgehensweisen aus der Praxis verwenden.
Was ich hier mit meine richtlinienist meist benutzerdefinierte Anweisungen während des Tutorials. Ich werde nicht versuchen, Ihnen beizubringen, wie eingebaute Anweisungen verwendet werden Wiederholung
, ng-show
, Ich werde Ihnen zeigen, wie Sie mit benutzerdefinierten Anweisungen Ihre eigenen Komponenten erstellen können.
Angenommen, Sie haben eine E-Commerce-Anwendung zu Büchern und zeigen bestimmte Buchdetails in verschiedenen Bereichen an, wie z. B. Kommentare, Benutzerprofilseiten, Artikel usw. Ihr Buchdetails-Widget kann wie folgt aussehen:
In diesem Widget gibt es ein Buchbild, einen Titel, eine Beschreibung, Kommentare und eine Bewertung. Das Sammeln dieser Informationen und das Einfügen eines bestimmten dom-Elements kann an allen Stellen, an denen Sie sie verwenden möchten, schwierig sein. Lassen Sie uns diese Ansicht mithilfe einer AngularJS-Direktive mit einem Widget versehen.
angle.module ('masteringAngularJsDirectives', []) .directive ('book', function () return einschränken: 'E', Gültigkeitsbereich: data: '=', templateUrl: 'templates / book-widget.html ')
Im obigen Beispiel wurde eine Direktive verwendet, um zuerst eine Direktive zu erstellen. Der Name der Direktive lautet Buch
. Diese Direktive gibt ein Objekt zurück und lasst uns ein wenig über dieses Objekt sprechen. beschränken
dient zur Definition des Direktive-Typs, und es kann sein EIN
(EINTribut),C
(CMädel), E
(Element) undM
(coMment). Sie können die Verwendung von jeweils unten sehen.
Art | Verwendungszweck |
---|---|
EIN | Buch> |
C | |
E | <Buch data = "book_data">Buch> |
M |
Umfang
dient zur Verwaltung des Richtlinienbereichs. In diesem Fall werden die Buchdaten mithilfe von in die Direktive-Vorlage übertragen "="
Bereichstyp. Ich werde in den folgenden Abschnitten ausführlich über den Umfang sprechen. templateUrl
wird verwendet, um eine Ansicht aufzurufen, um mithilfe von Daten, die in den Geltungsbereich der Richtlinie übertragen werden, bestimmten Inhalt wiederzugeben. Sie können auch verwenden Vorlage
und geben Sie HTML-Code direkt wie folgt ein:
… Vorlage: 'Buchinfo'…
In unserem Fall haben wir eine komplizierte HTML-Struktur, und deshalb habe ich die templateUrl
Möglichkeit.
Direktiven werden in der JavaScript-Datei Ihres AngularJS-Projekts definiert und in der HTML-Seite verwendet. Es ist möglich, AngularJS-Direktiven in HTML-Seiten wie folgt zu verwenden:
In dieser Verwendung wird der Direktionsname in Standard-HTML-Elementen verwendet. Angenommen, Sie verfügen über ein rollenbasiertes Menü in Ihrer E-Commerce-Anwendung. Dieses Menü wird entsprechend Ihrer aktuellen Rolle gebildet. Sie können eine Direktive definieren, um zu entscheiden, ob das aktuelle Menü angezeigt werden soll oder nicht. Ihr HTML-Menü kann wie folgt aussehen:
und die Richtlinie wie folgt:
app.directive ("restricted", function () return einschränken: 'A', link: function (scope, element, attrs) // Einige Auth-Check-Funktion var isAuthorized = checkAuthorization (); if (! isAuthorized) element.css ('display', 'none');)
Wenn Sie die beschränkt
Direktive im Menüelement als Attribut können Sie für jedes Menü eine Zugriffsebenenprüfung durchführen. Wenn der aktuelle Benutzer nicht berechtigt ist, wird dieses bestimmte Menü nicht angezeigt.
Also, was ist das? Verknüpfung
Funktion dort? Die Link-Funktion ist einfach die Funktion, die Sie zum Ausführen von richtlinienspezifischen Operationen verwenden können. Die Direktive gibt nicht nur HTML-Code aus, indem sie einige Eingaben bereitstellt. Sie können auch Funktionen an das Direktive-Element binden, einen Dienst aufrufen und den Direktive-Wert aktualisieren und Direktive-Attribute abrufen, wenn es sich um einen handelt E
Typanweisung usw.
Sie können den Direktivenamen in HTML-Elementklassen verwenden. Angenommen, Sie verwenden die obige Direktive als C
, Sie können die Direktive aktualisieren beschränken
wie C
und benutze es wie folgt:
Jedes Element hat bereits eine Klasse zum Styling und als beschränkt
Klasse wird hinzugefügt, es ist eigentlich eine Direktive.
Sie müssen keine Direktive in einem HTML-Element verwenden. Sie können ein eigenes Element erstellen, indem Sie eine AngularJS-Direktive mit einer E
Beschränkung. Angenommen, Sie haben ein Benutzer-Widget in Ihrer Anwendung, das angezeigt werden soll Nutzername
, Benutzerbild
, und Ruf
an mehreren Stellen in Ihrer Anwendung. Möglicherweise möchten Sie eine Anweisung wie diese verwenden:
app.directive ("user", function () return einschränken: 'E', Verknüpfung: function (scope, element, attrs)) scope.username = attrs.username; scope.avatar = attrs.avatar; = attrs.reputation;, Vorlage: 'Benutzername: username, Avatar: avatar, Ruf: Reputation')
Der HTML-Code lautet:
Im obigen Beispiel wird ein benutzerdefiniertes Element erstellt und einige Attribute werden wie angegeben Nutzername
, Benutzerbild
, und Ruf
. Ich möchte auf den Link-Funktionskörper aufmerksam machen. Elementattribute werden dem Geltungsbereich der Direktive zugewiesen. Der erste Parameter der Link-Funktion ist der Geltungsbereich der aktuellen Direktive. Der dritte Parameter der Direktive ist das Attributobjekt der Direktive. Das bedeutet, dass Sie jedes Attribut aus der benutzerdefinierten Direktive mit lesen können attrs.attr_name
. Attributwerte werden dem Bereich zugewiesen, sodass sie in der Vorlage verwendet werden.
Tatsächlich können Sie diese Operation auf eine kürzere Art und Weise durchführen, und ich werde später darüber sprechen. Dieses Beispiel dient zum Verständnis der Hauptidee der Verwendung.
Diese Verwendung ist nicht sehr häufig, aber ich werde zeigen, wie man sie benutzt. Angenommen, Sie benötigen ein Kommentarformular, damit Ihre Anwendung an vielen Stellen verwendet werden kann. Sie können dies tun, indem Sie die folgende Anweisung verwenden:
app.directive ("comment", function () return einschränken: 'M', Vorlage: '')
Und im HTML-Element:
Jede Direktive hat ihren eigenen Geltungsbereich, Sie müssen jedoch mit der Direktive Deklaration auf die Datenbindung achten. Angenommen, Sie implementieren die Korb
Teil Ihrer E-Commerce-Anwendung. Auf der Warenkorbseite haben Sie bereits Artikel hinzugefügt. Jeder Artikel hat ein Betragsfeld, mit dem Sie auswählen können, wie viele Artikel Sie kaufen möchten.
Hier ist die Anweisung der Richtlinie:
app.directive ("item", function () return einschränken: 'E', link: function (scope, element, attrs) scope.name = attrs.name;, Vorlage: 'Name: Name Betrag auswählen: Ausgewählter Betrag: Anzahl')
Und um drei Elemente in HTML anzuzeigen:
Das Problem hierbei ist, dass bei jeder Auswahl des Betrags des gewünschten Artikels alle Betragsabschnitte der Artikel aktualisiert werden. Warum? Weil es eine bidirektionale Datenbindung mit einem Namen gibt Anzahl
, aber der Umfang ist nicht isoliert. Um den Umfang zu isolieren, fügen Sie einfach ein Umfang:
auf das Direktive-Attribut im Rückgabeabschnitt:
app.directive ("item", function () return einschränken: 'E', Gültigkeitsbereich: , link: function (scope, element, attrs) scope.name = attrs.name;, template: 'Name: Name Betrag auswählen: Ausgewählter Betrag: Anzahl')
Dies hat zur Folge, dass Ihre Anweisung einen eigenen isolierten Geltungsbereich hat, sodass die bidirektionale Datenbindung innerhalb dieser Anweisung separat erfolgt. Ich werde auch über das erwähnen Umfang
Attribut später.
Der Hauptvorteil der Direktive besteht darin, dass es sich um eine wiederverwendbare Komponente handelt, die problemlos verwendet werden kann einige zusätzliche Attribute angeben zu dieser Richtlinie. Wie ist es jedoch möglich, einen zusätzlichen Wert, eine Bindung oder einen Ausdruck an eine Direktive zu übergeben, damit Daten innerhalb der Direktive verwendet werden können?
"@" Umfang: Diese Art von Bereich wird verwendet, um Wert an den Richtlinienbereich zu übergeben. Angenommen, Sie möchten ein Widget für eine Benachrichtigungsnachricht erstellen:
app.controller ("MessageCtrl", function () $ scope.message = "Produkt wurde erstellt!";) app.directive ("notification", function () return einschränken: 'E', Geltungsbereich: message: '@' , Vorlage: 'Botschaft');
und du kannst verwenden:
In diesem Beispiel wird der Nachrichtenwert einfach dem Direktionsbereich zugewiesen. Der gerenderte HTML-Inhalt wird sein:
Produkt erstellt!
"=" Umfang: In diesem Bereichstyp werden Bereichsvariablen anstelle der Werte übergeben, was bedeutet, dass wir nicht übergeben werden Botschaft
, wir werden passieren Botschaft
stattdessen. Der Grund für diese Funktion ist das Erstellen einer bidirektionalen Datenbindung zwischen der Direktive und den Seitenelementen oder Controllern. Lass es uns in Aktion sehen.
.Direktive ("bookComment", function () return einschränken: 'E', Gültigkeitsbereich: text: '=', template: '')
In dieser Anweisung versuchen wir, ein Widget für die Anzeige von Kommentartexten zu erstellen, um einen Kommentar für ein bestimmtes Buch zu erstellen. Wie Sie sehen, erfordert diese Direktive ein Attribut Text
Erstellen einer bidirektionalen Datenbindung zwischen anderen Elementen auf den Seiten. Sie können dies auf der Seite verwenden:
Dies ist das Textfeld in der Direktive
Dadurch wird einfach ein Textfeld auf der Seite angezeigt. Fügen Sie also etwas mehr hinzu, um mit dieser Anweisung zu interagieren:
Dies ist das Textfeld auf der Seite
Dies ist das Textfeld in der Direktive
Immer wenn Sie etwas in das erste Textfeld eingeben, wird es auch in das zweite Textfeld eingegeben. Sie können das umgekehrt tun. In der Direktive haben wir die Gültigkeitsbereichsvariable übergeben KommentarText
Anstelle des Werts ist diese Variable die Datenbindungsreferenz zum ersten Textfeld.
"&" Umfang: Wir können den Wert und den Verweis auf Anweisungen weitergeben. In diesem Bereichstyp wird beschrieben, wie Ausdrücke an die Direktive übergeben werden. In realen Fällen müssen Sie möglicherweise eine bestimmte Funktion (Ausdruck) an Anweisungen übergeben, um eine Kopplung zu verhindern. Manchmal müssen Direktiven nicht viel über die Idee hinter den Ausdrücken wissen. Eine Direktive mag beispielsweise das Buch für Sie, aber sie weiß nicht, wie sie das machen soll. Um dies zu tun, können Sie einer Struktur wie folgt folgen:
.Direktive ("likeBook", function () return einschränken: 'E', Gültigkeitsbereich: wie: '&', template: '')
In dieser Direktive wird ein Ausdruck über die Schaltfläche an die Direktive-Schaltfläche übergeben mögen
Attribut. Definieren Sie eine Funktion im Controller und übergeben Sie sie an die Direktive im HTML.
$ scope.likeFunction = function () alert ("Ich mag das Buch!")
Dies wird sich innerhalb des Controllers befinden und die Vorlage lautet:
likeFunction ()
kommt vom Controller und wird an die Direktive übergeben. Was ist, wenn Sie einen Parameter an übergeben möchten likeFunction ()
? Beispielsweise müssen Sie möglicherweise einen Bewertungswert an den übergeben likeFunction ()
. Es ist sehr einfach: Fügen Sie der Funktion im Controller einfach ein Argument hinzu, und fügen Sie der Direktive ein Eingabeelement hinzu, um die Startzählung des Benutzers anzufordern. Sie können dies wie folgt tun:
.Direktive ("likeBook", function () return einschränken: 'E', Gültigkeitsbereich: wie: '&', template: '
'+'')
$ scope.likeFunction = function (star) alert ("Ich mag das Buch!" und gab "+ Stern +" Stern. ")
Wie Sie sehen, stammt das Textfeld aus der Direktive. Der Textfeldwert ist an das Funktionsargument wie gebunden wie (star: starCount)
. Star
ist für die Controller-Funktion und starCount
für die Textfeldbindung.
Manchmal verfügen Sie möglicherweise über eine Funktion, die in mehreren Anweisungen vorhanden ist. Sie können in eine übergeordnete Direktive eingefügt werden, damit sie von den untergeordneten Direktiven vererbt werden.
Lassen Sie mich ein reales Beispiel geben. Sie möchten statistische Daten senden, wenn Kunden den Mauszeiger oben in einem bestimmten Buch bewegen. Sie können ein Mausklickereignis für die Book-Direktive implementieren. Was aber, wenn es von einer anderen Direktive verwendet wird? In diesem Fall können Sie die Vererbung der Anweisungen wie folgt verwenden:
app.directive ('mouseClicked', function () return einschränken: 'E', Gültigkeitsbereich: , Controller: "MouseClickedCtrl as mouseClicked")
Dies ist eine übergeordnete Direktive, die von untergeordneten Direktiven vererbt wird. Wie Sie sehen, gibt es ein Controller-Attribut der Direktive mit der Direktive "as". Definieren wir auch diesen Controller:
app.controller ('MouseClickedCtrl', Funktion ($ element) var mouseClicked = this; mouseClicked.bookType = null; mouseClicked.setBookType = function (type) mouseClicked.bookType = type; $ element.bind ("click", function () alert ("Art des Buches:" + mouseClicked.bookType + "zur statistischen Analyse gesendet!");))
In diesem Controller setzen wir einfach eine Controller-Instanz der Variablen bookType
durch die Verwendung von untergeordneten Anweisungen. Wenn Sie auf ein Buch oder eine Zeitschrift klicken, wird der Elementtyp an den Back-End-Service gesendet (ich habe eine Warnfunktion verwendet, um die Daten anzuzeigen). Wie können Kinderrichtlinien diese Richtlinie verwenden??
app.directive ('ebook', function () return erfordert: "mouseClicked"), link: function (scope, element, attrs, mouseClickedCtrl) mouseClickedCtrl.setBookType ("EBOOK");) .directive (' magazin ', function () return erfordert: "mouseClicked", link: function (scope, element, attrs, mouseClickedCtrl) mouseClickedCtrl.setBookType ("MAGAZINE");
Wie Sie sehen, verwenden untergeordnete Direktiven die benötigen
Schlüsselwort, um die übergeordnete Direktive zu verwenden. Ein weiterer wichtiger Punkt ist das vierte Argument der Link-Funktion in den untergeordneten Anweisungen. Dieses Argument bezieht sich auf das Controller-Attribut der übergeordneten Direktive, dh die untergeordnete Direktive kann die Controller-Funktion verwenden setBookType
im Controller. Wenn das aktuelle Element ein eBook ist, können Sie die erste Direktive verwenden. Wenn es sich um eine Zeitschrift handelt, können Sie die zweite Direktive verwenden:
Spiel der Throne (klick mich)
PC World (klick mich)
Untergeordnete Direktiven sind wie eine Eigenschaft der übergeordneten Direktive. Wir haben die Verwendung des Mausklickereignisses für jede untergeordnete Direktive eliminiert, indem dieser Abschnitt in die übergeordnete Direktive eingefügt wurde.
Wenn Sie Direktiven in der Vorlage verwenden, sehen Sie auf der Seite die kompilierte Version der Direktive. Manchmal möchten Sie die tatsächliche Verwendung der Direktiven zu Debugging-Zwecken sehen. Um die nicht kompilierte Version des aktuellen Abschnitts anzuzeigen, können Sie verwenden nicht bindend
. Angenommen, Sie haben ein Widget, das die beliebtesten Bücher druckt, und hier ist der Code dafür:
Die Gültigkeitsvariable des Buches stammt vom Controller. Die Ausgabe lautet wie folgt:
Wenn Sie wissen möchten, welche Direktive hinter dieser kompilierten Ausgabe steht, können Sie diese Version des Codes verwenden:
Dieses Mal ist die Ausgabe wie folgt:
Bis jetzt ist es cool, aber was ist, wenn wir sowohl die nicht kompilierte als auch die kompilierte Version des Widgets sehen möchten? Es ist an der Zeit, eine benutzerdefinierte Direktive zu schreiben, die einen fortgeschrittenen Debugging-Vorgang ausführt.
app.directive ('customDebug', Funktion ($ compile) return terminal: true, Link: Funktion (Gültigkeitsbereich, Element) var currentElement = element.clone (); currentElement.removeAttr ("custom-debug"); var newElement = $ compile (currentElement) (scope); element.attr ("style", "border: 1px durchgehend rot"); element.after (newElement);
In dieser Anweisung klonen wir das Element, das sich im Debug-Modus befindet, so dass es nach einigen Operationen nicht geändert wird. Entfernen Sie nach dem Klonen die benutzerdefiniertes Debuggen
Direktive, um nicht als Debug-Modus zu fungieren, und kompiliert ihn dann mit $ komplizieren
, das ist bereits in der Richtlinie eingespritzt. Wir haben dem Debug-Modus-Element einen Stil gegeben, um den debuggten hervorzuheben. Das Endergebnis ist wie folgt:
Sie können Ihre Entwicklungszeit sparen, indem Sie diese Art der Debugging-Anweisung verwenden, um die Ursache für Fehler in Ihrem Projekt zu ermitteln.
Wie Sie bereits wissen, ist das Testen von Einheiten ein sehr wichtiger Bestandteil der Entwicklung, um den von Ihnen geschriebenen Code vollständig zu kontrollieren und mögliche Fehler zu vermeiden. Ich werde mich nicht eingehend mit Unit-Tests beschäftigen, sondern Ihnen einen Hinweis darauf geben, wie Sie Anweisungen auf verschiedene Arten testen können.
Ich werde Jasmin für Unit Tests und Karma für den Unit Test Runner verwenden. Um Karma zu verwenden, installieren Sie es einfach global, indem Sie es ausführen npm install -g karma karma-cli
(Sie müssen Node.js und npm auf Ihrem Computer installiert haben). Öffnen Sie nach der Installation die Befehlszeile, wechseln Sie zum Stammordner des Projekts und geben Sie Folgendes ein Karma init
. Sie werden einige Fragen stellen (siehe unten), um Ihre Testanforderungen festzulegen.
Ich verwende Webstorm für die Entwicklung. Wenn Sie auch Webstorm verwenden, klicken Sie einfach mit der rechten Maustaste auf karma.conf.js und wählen Sie Lauf karma.conf.js. Dadurch werden alle Tests ausgeführt, die im Karma-Conf konfiguriert sind. Sie können auch Tests mit ausführen Karma-Start
Befehlszeile im Stammordner des Projekts. Das ist alles über die Umgebungseinstellung, also wechseln wir zum Testteil.
Nehmen wir an, wir wollen die Buchrichtlinie testen. Wenn wir der Direktive einen Titel übergeben, sollte sie in einer Buchdetailansicht zusammengefasst werden. Also lasst uns anfangen.
beschreiben ("Book Tests", function () var-Element; var scope; beforeEach (Modul ("masteringAngularJsDirectives")) beforeEach (inject (Funktion ($ compile, $ rootScope)) scope = $ rootScope; element = angle.element ( ""); $ compile (Element) ($ rootScope) Geltungsbereich. $ digest ())); it (" Anweisung sollte erfolgreich kompiliert werden ", function () expect (element.html ()). toBe (" test ") )));
Im obigen Test testen wir eine neue Direktive namens Buchprüfung
. Diese Direktive nimmt das Argument an Titel
und erstellt ein div mit diesem Titel. Im Test rufen wir vor jedem Testabschnitt unser Modul auf MasteringAngularJsDirectives
zuerst. Dann generieren wir eine Direktive namens Buchprüfung
. In jedem Testschritt wird die Direktive-Ausgabe getestet. Dieser Test dient nur zur Überprüfung der Werte.
In diesem Abschnitt werden wir den Geltungsbereich der Richtlinie testen Buchprüfung
. Diese Anweisung generiert eine Buchdetailansicht auf der Seite. Wenn Sie auf diesen Detailabschnitt klicken, wird eine Bereichsvariable aufgerufen angesehen
wird als gesetzt wahr
. In unserem Test prüfen wir, ob angesehen
wird auf true gesetzt, wenn das Klickereignis ausgelöst wird. Die Richtlinie lautet:
.Direktive ('booktest', function () return einschränken: 'E', Gültigkeitsbereich: title: '@', ersetzen: true, template: 'Titel', link: function (scope, element, attrs) element.bind ("click", function () console.log ("Buch angesehen!"); scope.viewed = true;); )
Um ein Ereignis in AngularJS innerhalb der Direktive auf ein Element festzulegen, können Sie das verwenden Verknüpfung
Attribut. In diesem Attribut haben Sie das aktuelle Element, das direkt an ein Klickereignis gebunden ist. Um diese Anweisung zu testen, können Sie Folgendes verwenden:
beschreiben ("Book Tests", function () var-Element; var scope; beforeEach (Modul ("masteringAngularJsDirectives")) beforeEach (inject (Funktion ($ compile, $ rootScope)) scope = $ rootScope; element = angle.element ( ""); $ compile (Element) ($ rootScope) Geltungsbereich. $ digest ())); it (" Geltungsbereich sollte wahr sein, wenn ein Buch gefällt ") function () element.triggerHandler (" click "); expect ( element.isolateScope (). angesehen) .toBe (true);););
Im Testabschnitt wird mit click ein Klickereignis ausgelöst element.triggerHandler ("click")
. Wenn ein Klickereignis ausgelöst wird, muss die angezeigte Variable als festgelegt werden wahr
. Dieser Wert wird durch Verwendung von bestätigt Expect (element.isolateScope (). betrachtet) .toBe (true)
.
AngularJS ist das Beste, um modulare und testbare Webprojekte zu entwickeln. Richtlinien sind eine der besten Komponenten von AngularJS. Je mehr Sie über AngularJS-Richtlinien wissen, desto modularer und überprüfbarer Projekte können Sie entwickeln.
In diesem Tutorial habe ich versucht, Ihnen die bewährten Vorgehensweisen in Bezug auf Richtlinien zu zeigen. Denken Sie daran, dass Sie viel Übung machen müssen, um die Logik hinter den Richtlinien zu verstehen. Ich hoffe, dieser Artikel hilft Ihnen, die Richtlinien von AngularJS gut zu verstehen.