2013-04-09 13 views
13

Angular bietet uns einen Mechanismus zum Schreiben von Direktiven - was äußerst wirkungsvoll ist. Aber die Sache, die ich mich frage, ist - in welchem ​​Szenario solltest du eigentlich eine eigene benutzerdefinierte Direktive schreiben?Wann soll ich eine Direktive schreiben?

Wir sehen immer wieder Fragen in und um Stack Overflow mit verschiedenen Leuten, die versuchen, Direktiven zu schreiben, die (meiner Meinung nach) nicht geschrieben werden müssen. In den meisten Fällen können sie mit einer Kombination aus Wiederholen, Wechseln und Zeigen gelöst werden. Sehen Sie Beispiele für Fragen, die Richtlinien enthalten, die meiner Meinung nach keine Richtlinien sein sollten!

https://stackoverflow.com/questions/16101073/angularjs-directive-is-not-working-in-ie-10

Fire button click in AngularJS

angularjs: using a directive inside the ui-bootstrap modal

Einige Szenarien Beispiele. Ich nehme sie nicht auf ... weil ich sicher bin, dass niemandem klar ist, wann wir eine Richtlinie verwenden/schreiben sollten.

Wir sehen Szenarien, wo Menschen Richtlinien als Mechanismus für Templating verwenden. Ist das der richtige Weg, Dinge zu tun? Oder gibt es einen besseren Weg? (ng-include vielleicht?) Gibt es irgendwelche Vor- und Nachteile bei der Verwendung von Richtlinien als Templating-Mechanismus? Der Grund für diese Frage ist, dass ich mich manchmal frage, ob Leute Direktiven schreiben, weil sie aus der JQuery-Welt das erste Ding sind, das ihnen einfällt, DOM-Manipulationscode zu schreiben und da der Angular-Weg nicht das DOM in Controllern manipuliert, geht alles zum Schreiben all dieser Code in einer Direktive.

EDIT:

ich diese Verwirrung glauben (der Dinge in einer Richtlinie schiebend) entsteht, weil Angular kein separates Konzept einer „Ansicht“ haben - anders als Backbone (die nur einen „Blick“ hat aber keine Komponente!). Direktiven sind erstaunlich bei der Definition von Komponenten - Aber ich denke, wenn Sie sie verwenden, um "Ansichten" zu erstellen, werden Sie etwas von der "eckigen" Art und Weise verlieren. Dies ist jedoch meine Meinung, weshalb ich mich erbitte, was der Rest der eckigen Gemeinschaft denkt.

Das Gute an einfacheren Anweisungen (Anweisungen, die nur eine Sache machen!) Ist, dass sie absolut einfach zu testen sind. Wenn Sie sich alle ng-Anweisungen anschauen, machen sie alle eine Sache und tun das ziemlich gut.

Was ist der beste Weg, um wiederverwendbare "Ansichten" (keine Komponenten!) In Angular zu definieren? Sollte das in einer Richtlinie geschrieben werden? Oder gibt es einen besseren Weg?

Es wäre toll, wenn einer der Angular Devs eine Meinung dazu hätte!

+1

Sobald Sie DOM-Manipulation machen wollen, müssen Sie eine Direktive schreiben. Controller sollten keine einzige Manipulation in ihnen haben. Aber die Direktive kann Controller in sich haben. – mpm

+0

Directive Controller sind aus anderen Gründen. Diese Controller und die normalen Controller sind unterschiedlich. – ganaraj

Antwort

10

Nun ... eine recht gute Frage.

Ich glaube, dass Richtlinien hauptsächlich für "extending HTML so you can build a DSL" gedacht sind, um die Produktivität und Codequalität zu verbessern.

Die Frage ist, dass dies durch Komponieren Dinge erreicht wird. Aber es ist von am wichtigsten, dass wir verstehen, dass die Richtlinie nicht nur über visuelle Komponenten, nur Templates, sondern auch über das Verhalten.

Zusammengefasst Direktiven Sie könnten:

  1. eine DSL zu Elemente erstellen erweitern Verhalten
  2. DSL-Widgets erstellen, so dass Sie sich
  3. Verpackung bereits vorhandenen Komponenten Wiederholung stoppen, Kauf von Produktivität.
  4. Optimierung

augmentierenden Verhalten ist nichts anderes als das Verhalten componentizing. Beispielsweise fügt ng-click das anklickbare Verhalten zu jedem Element hinzu. Stellen Sie sich vor, Sie erstellen eine App mit Dutzenden von ziehbaren Elementen. Dann würden Sie eine Direktive erstellen, um das Elementverhalten zu erweitern und es ziehbar zu machen, ohne das Element visual zu berühren (<span draggable>Test</span>). Noch ein weiteres Beispiel, stell dir vor, du hättest spezielle Hinweise zum Maus-Hover. title Attribut ist nicht dafür geeignet, dann können Sie Ihr eigenes my-title Attribut erstellen, das automatisch Ihren "speziellen Hinweis" auf Maus-Hover (<span my-title="Some caption">Test</span>) erstellt.

Und wenn Sie eine App entwickeln, haben Sie viele domänenspezifische Konzepte und Verhaltensweisen. Stackoverflow zum Beispiel hat ein starkes Abstimmungskonzept. Sie können Fragen, Antworten, Kommentare ... nach oben/unten abstimmen. So könnten Sie eine wiederverwendbare votable-Direktive erstellen, die "Wahlverhalten" und "Wahl-Widget" (Pfeile nach oben/unten) zu jedem beliebigen Element hinzufügen würde.

Diese letzte gibt uns ein anderes Gesicht: Templating. Nicht nur für faule, sondern auch um die Codequalität und Wartbarkeit nach DRY principle zu verbessern. Wenn Sie Controller-Code, HTML-Struktur oder irgendetwas anderes wiederholen, warum nicht Templates und Komponierens, oder? Richtlinie ist dein Typ für diesen Job.

Natürlich haben Sie auch einige generische Anwendung von Direktiven. Viele Anwendungen (um nicht alle zu sagen) sind auf anklickbare Elemente angewiesen, deshalb haben wir zum Beispiel eine ng-click. Viele Anwendungen haben Upload-Bereiche. Und was würdest du jQuery machen? Sie würden ein jQuery-Plugin erstellen. Recht? In Angular würden Sie ein Angular Widget (mit Direktiven) erstellen. Sie können sogar ein bereits vorhandenes Plugin mit einer Direktive umschließen und noch einmal sein Verhalten erweitern, damit es problemlos mit Ihrer Anwendung kommunizieren kann.

In Bezug auf Verpackung Plugins, zu jedem jQuery-Plugin (könnte aber sein MooTools, Ext ...) Sie wird einen Controller erstellen müssen, rufen Sie $('element').plugin() darauf und Pflege, dass jQuery Ereignisse ändern und Ihr Umfang verdauen $ für dich. Dies ist eine weitere perfekte Anwendung der Richtlinie. Sie können eine Direktive erstellen, die .plugin() auf Ihr Element anwendet, die Ereignisse überwacht und Ihren Bereich für Sie ändert/verdaut. Dies ist, was Angular UI Project dreht sich um, werfen Sie einen Blick.

Ein letzter Punkt ist die Optimierung. Ich habe vor kurzem erstellt und App, die Tabellen mit dynamischen Spalten und Zeilen (ein Raster) erstellt. Die Frage ist, dass Daten in Echtzeit aktualisiert werden! Und die ng-repeat innerhalb von ng-repeat, um Header zu erstellen, löschte die Anwendungs-Performance (verschachtelte Schleifen in jedem $apply Zyklus, jede halbe Sekunde). Sie können also eine Direktive erstellen, die die Spaltenvorlage erstellt und immer noch ng-repeat darin verwendet, aber Sie würden nur bei der Spaltenedition eine Schleife durch die Spalten haben.

Also, Einwickeln, ich glaube Richtlinien sind über componentizing Verhalten und Form (Templat), die Sie kaufen und die Produktivität beim Code-Qualität.

2

Ich persönlich schreibe Direktiven ziemlich viel, da sie mein Programm viel deklarativer machen.

Ein Beispiel: in einem JSON -> HTML-Formular Parser Ich habe vor kurzem habe ich eine „Form-Element“ Richtlinie, die die JSON-Element eine Schaffung der notwendigen Richtlinien, wie es Kinder analysiert. Auf diese Weise habe ich eine Direktive für jeden Feldtyp mit spezifischen Verhaltensweisen und Methoden. Ein gemeinsames Verhalten, das von allen Elementen gemeinsam genutzt wird, befindet sich in der form-element-Direktive.

Auf diese Weise ist ein Gruppenelement eine Direktive mit einer ng-Wiederholung in der Vorlage, und ein Titelelement ist so einfach wie eine h1. Aber alle können dasselbe bedingte Verhalten haben (eine Gruppe kann nur erscheinen, wenn ein vorheriges Feld beispielsweise einen bestimmten Wert hat).Und alles extrem sauber - immer wenn ich etwas hinzufügen/ändern muss, bleibt alles perfekt und das HTML ist extrem deklarativ.

EDIT - ein Code-Snippet enthalten, wie über Kommentare angefordert.

/** 
    * Form Element 
    * ============ 
    * 
    * Handles different elements: 
    * Assigns diferent directives according to the element type 
    * Instanstiates and maintains the active property on the formElem 
    */ 
    .directive("formElement", ['$compile', function($compile){ 
    return{ 
     restrict: "E", 
     scope:{formElemModel: '='}, 
     link: function(scope, element, attrs){ 
      var template = ''; 
      var type = scope.formElem.type; 
      switch (type){ 
       case "field": 
        template = 
         "<form-field-"+scope.formElemModel.fieldType+" ng-switch-when='true'>\ 
         </form-field-"+scope.formElemModel.fieldType+">"; 
        break; 
       default: 
        template = "<form-"+type+" ng-switch-when='true' ></form-"+type+">"; 
        break; 
      } 
      element.html(template); 
      $compile(element.contents())(scope); 

     // Active state of form Element 
     scope.formElem.active = true; 
     scope.testActive = function(){ 
      if(scope.$parent.formElem && scope.$parent.formElem.active == false){ 
      scope.formElem.active = false; 
      } 
      else{ 
      scope.formElem.active = 
       scope.meetsRequirements(scope.formElem.requirements); 
      } 
     } 
     scope.$watch("meetsRequirements(formElem.requirements)", scope.testActive); 
     scope.$watch("$parent.formElem.active", scope.testActive); 
     } 
    } 
    }]) 
+0

so verwenden Sie es im Grunde für Templating. Das ist ein Anwendungsfall. Wenn es Dir gut geht, Direktiven auf Elementebene zu erstellen (was bedeutet, dass Du Dich nicht um die HTML-Validierung kümmerst!), Ist das völlig in Ordnung. Haben Sie in Erwägung gezogen, ng-include anstelle einer Direktive für dieses Szenario zu verwenden? Natürlich ist eine benutzerdefinierte benannte Direktive viel semantischer. Aber ich frage mich nur. Vielleicht ist die Frage - ist es sogar möglich, das gleiche mit ng-include zu tun! – ganaraj

+0

In ein paar Fällen (wie eine einfache h1) kann es nur Templating sein, aber es ist sicherlich nicht auf kompliziertere Elemente, wie ein Ajax laden mehrere Auswahl mit select2, und Rückrufe in der JSON definiert :) Es ist wirklich nicht Es ist nicht möglich, das meiste von dem zu tun, was (in meinem Fall) in einem ng-include getan wird, aber selbst in den Fällen, wo es ist, warum? Der Versuch, extrem komplexe Strukturen unter Verwendung von nur HTML zu erstellen, scheint das Vorlagensystem zu überlasten, und natürlich (und im Fall von h1) würde ich meine eine Zeile der Inline-Vorlage durch einen zusätzlichen Aufruf einer HTML-Datei ersetzen, alle mit zusätzlichen Headern . –

+0

(double post, tut mir leid) in meinem Fall würde ng-include bedeuten a) 15+ HTML-Dateien nur für Felder oder b) Lasten von ng-switch-Direktiven (die nützlich wie sie sind, neigen dazu, ziemlich chaotisch) und wenn ich Ich wollte ein spezifisches Modellverhalten, entweder indem ich Funktionen auf einen chaotischen Dump-Controller werfe oder 10+ Controller habe, die Direktiven sein könnten (und sollten). * (Auch wenn ich es beachten sollte, macht es all-js macht es einfach zu verwenden als das Widget, das es ist) * In Bezug auf HTML-Validierung können Sie all dies mit Klassen oder Daten-Präfix-Attribute tun, obwohl ich zugeben muss es ist wahr, es ist mir egal: P –

Verwandte Themen