2013-04-09 13 views
13

Angular zapewnia nam mechanizm pisania dyrektyw - który jest niezwykle potężny w tym, co potrafi. Zastanawiam się jednak, w jakim scenariuszu faktycznie piszesz własną dyrektywę.Kiedy napisać dyrektywę?

Wciąż widzimy pytania w Stack Overflow i wokół nich, z różnymi ludźmi próbującymi pisać dyrektywy, które (moim zdaniem) nie muszą być napisane w pierwszej kolejności. W większości przypadków można je rozwiązać za pomocą kombinacji powtarzania, przełączania i pokazywania. Zobacz przykłady pytań zawierających dyrektywy, które moim zdaniem nie powinny być dyrektywami w pierwszej kolejności!

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

niektórych scenariuszach przykładach. W każdym razie ich nie wybieram, ponieważ jestem pewien, że nikomu nie jest jasne, kiedy powinniśmy używać/pisać dyrektywę.

Widzimy scenariusze, w których ludzie używają dyrektyw jako mechanizmu szablonowego. Czy to właściwy sposób robienia rzeczy? Czy jest jakiś lepszy sposób? (ng-include maybe?) Czy są jakieś zaległości/wady stosowania dyrektyw jako mechanizmu szablonowego? Powodem tego pytania jest to, że czasami zastanawiam się, czy ludzie piszą dyrektywy, ponieważ pochodząc ze świata jquery, pierwszą rzeczą, o której mogą myśleć jest pisanie kodu manipulującego DOMem, a ponieważ metoda Angulara nie polega na manipulowaniu DOM w kontrolerach, wszystko to grawituje w kierunku pisania cały ten kod w dyrektywie.

EDIT:

Wierzę tego zamieszania (od wtykając rzeczy wewnątrz dyrektywy) pojawia się, ponieważ kątowe nie posiada osobnego pojęcia „Widok” - w przeciwieństwie szkieletowe (który ma tylko „widok”, ale bez komponentu!). Dyrektywy są niesamowite w definiowaniu komponentów - ale myślę, że jeśli użyjesz ich do stworzenia "widoków", stracisz część "kątowej" drogi. Takie jest moje zdanie - dlatego szukam odpowiedzi na pytanie pozostałych członków społeczności kanciastej.

Dobrą rzeczą w przypadku prostszych dyrektyw (dyrektyw, które robią tylko jedno!) Jest to, że są one absolutnie łatwe do przetestowania. Jeśli spojrzysz na wszystkie dyrektywy, wszyscy robią jedno i robią to całkiem dobrze.

Jaki jest najlepszy sposób definiowania wielokrotnych użytecznych "widoków" (nie komponentów!) W Angular? Czy powinno to być zapisane w dyrektywie? Czy jest jakiś lepszy sposób?

Byłoby wspaniale, gdyby jeden z Angular Dev's miał opinię w tej sprawie!

+1

jak tylko chcesz manipulować DOM, musisz napisać dyrektywę. Kontrolery nie powinny mieć w sobie ani jednej manipulacji. Ale dyrektywa może mieć w sobie kontrolerów. – mpm

+0

Dyrektywy kontrolerów są z innych powodów. Te kontrolery i normalne sterowniki są różne. – ganaraj

Odpowiedz

10

Cóż ... całkiem dobre pytanie.

Uważam, że dyrektywy mają głównie na celu "extending HTML so you can build a DSL", podnosząc wydajność i jakość kodu.

Pytanie jest takie, że osiąga się to przez komponowanie elementów. Ale to jest najważniejsze, że rozumiemy, że dyrektywa nie dotyczy tylko komponentów wizualnych, ani szablonów, ale także, o zachowaniu.

Podsumowując, za pomocą dyrektyw można:

  1. utworzyć DSL powiększać elementy zachowania
  2. tworzyć DSL widgety, dzięki czemu można zatrzymać powtarzając sobie
  3. owijanie już nieistniejących komponentów, kupując ci wydajność.
  4. optymalizacja

Rozszerzanie zachowanie nie jest niczym więcej niż componentizing zachowanie. Na przykład ng-click dodaje klikalne zachowanie do dowolnego elementu. Wyobraź sobie, że tworzysz aplikację z dziesiątkami elementów możliwych do przeciągnięcia. Następnie stworzysz dyrektywę, która zwiększy zachowanie elementu, dzięki czemu będzie można go przeciągać bez dotykania elementu wizualnego (<span draggable>Test</span>). Jeszcze jeden przykład, wyobraź sobie, że będziesz miał specjalne wskazówki na temat wskaźnika myszy. Atrybut title nie nadaje się do tego, możesz więc utworzyć własny atrybut my-title, który automatycznie utworzy "specjalną wskazówkę" po najechaniu myszą (<span my-title="Some caption">Test</span>).

Podczas tworzenia aplikacji masz wiele koncepcji i zachowań związanych z konkretną domeną. Stackoverflow, na przykład, ma silną koncepcję głosowania. Możesz głosować w górę/w dół pytania, odpowiedzi, komentarze ... Możesz utworzyć dyrektywę wielokrotnego użytku votable, która dodaje "zachowanie głosowe" i "widget głosowania" (strzałki w górę/w dół), aby w efekcie uzyskać dowolny element.

Ten ostatni daje nam kolejną twarz: szablon. Nie tylko dla leniwych, ale także dla poprawy jakości kodu i łatwości konserwacji po DRY principle. Jeśli powtarzasz kod kontrolera, strukturę HTML lub cokolwiek innego, czemu nie szablonować i komponować, prawda? Dyrektywa to twój facet do tej pracy.

Oczywiście, masz również ogólne zastosowanie dyrektyw. Wiele aplikacji (nie mówiąc już o nich wszystkich) opiera się na elementach klikalnych, dlatego na przykład mamy ng-click. Wiele aplikacji ma obszary przesyłania. A co byś zrobił w myśleniu jQuery? Stworzyłbyś wtyczkę jQuery. Dobrze? W Angularu utworzysz Angular Widget (używając dyrektyw). Można nawet owinąć już istniejącą wtyczkę za pomocą dyrektywy, a po raz kolejny, rozszerzyć jego zachowanie, dzięki czemu można płynnie porozmawiać z aplikacją.

chodzi owijania wtyczek, każdemu plugin jQuery (ale może być MooTools, Ext ...), będziesz musiał stworzyć kontroler, zadzwoń $('element').plugin() na to, że zdarzenia i opiekuńczy jQuery zmienić i $ trawić swój zakres dla Ciebie. To kolejne doskonałe zastosowanie dyrektywy. Możesz utworzyć dyrektywę, która będzie stosować .plugin() na twoim elemencie, słuchając wydarzeń i zmieniając/trawiąc swój zasięg. O to właśnie chodzi, przyjrzyj się.

Ostatnim punktem jest optymalizacja. Ostatnio utworzyłem aplikację, która tworzy tabele z dynamicznymi kolumnami i wierszami (siatka). Chodzi o to, że dane są aktualizowane w czasie rzeczywistym! Natomiast powtórzenie polecenia ng-repeat w celu utworzenia nagłówków zabijało wydajność aplikacji (pętle zagnieżdżone w każdym cyklu $apply, co pół sekundy). Możesz więc utworzyć dyrektywę, która utworzy szablon kolumn i nadal będzie zawierała wewnątrz niego ng-repeat, ale będziesz mieć pętlę przez kolumny tylko podczas edycji kolumn.

Więc, owijając się, wierzę dyrektyw o componentizing zachowanie i forma (szablonów), co ci kupić producitivity i kodu jakość.

2

Ja osobiście dużo piszę o dyrektywach, ponieważ ich program jest bardziej deklaratywny.

Przykład: w JSON -> formularz HTML parser Zrobiłem niedawno, że stworzył „form-ele” dyrektywę, która analizuje element JSON tworząc niezbędne wskazówki, jak to dzieci. W ten sposób mam dyrektywę dla każdego typu pola, z określonym zachowaniem i metodami. Ponadto wszelkie wspólne zachowanie współużytkowane przez wszystkie elementy znajduje się w dyrektywie elementu formularza.

W ten sposób element grupy jest dyrektywą z ng-repeat w swoim szablonie, a element title jest tak prosty jak h1. Ale wszystkie mogą mieć takie samo zachowanie warunkowe (grupa może pojawić się tylko wtedy, gdy poprzednie pole ma określoną wartość, na przykład).A wszystko to wyjątkowo czyste - za każdym razem, gdy muszę dodać/zmienić, wszystko pozostaje idealnie ustawione, a html jest niezwykle deklaratywny.

EDYCJA - zawiera fragment kodu, zgodnie z prośbą za pośrednictwem komentarzy.

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

, więc zasadniczo używasz go do szablonów. To jest jeden przypadek użycia. Jeśli jesteś w porządku, tworząc dyrektywy na poziomie elementu (co oznacza, że ​​nie obchodzi Cię walidacja html!), To jest w porządku. Czy rozważałeś użycie ng-include zamiast dyrektywy dla tego scenariusza? Oczywiście niestandardowa nazwana dyrektywa jest znacznie bardziej semantyczna. Ale zastanawiam się. Być może pytanie brzmi - czy można to samo zrobić z ng-include! – ganaraj

+0

W kilku przypadkach (takich jak prosty h1) może to być tylko szablon, ale na pewno nie jest na bardziej skomplikowanych elementach, takich jak ładowanie ajax select multiple select2 i callback zdefiniowane w JSON :) To naprawdę nie jest Większość z tego, co się robi (w moim przypadku) można zrobić w Ng-Inc, ale nawet w przypadkach, w których jest, dlaczego? próba stworzenia niezwykle złożonych struktur przy użyciu tylko html wydaje się nadużywać systemu szablonów, i oczywiście (i w przypadku h1) zamieniłbym jedną linię wbudowanego szablonu na dodatkowe wywołanie do pliku html, wszystkie z dodatkowymi nagłówkami . –

+0

(podwójny wpis, przepraszam) w moim przypadku, ng-include oznaczałoby a) 15 + html plików tylko dla pól lub b) mnóstwo dyrektyw ng-switch (które są przydatne, ponieważ są raczej niechlujne) i jeśli poszukiwał określonego zachowania modelu, albo rzucając funkcje do niechlujnego kontrolera dumpa, albo mając 10+ kontrolerów, które mogłyby (i powinny) być tylko dyrektywami. * (Ponadto, jak powinienem zauważyć, posiadanie go jako all-js sprawia, że ​​jest on łatwy w użyciu jako widżet) * Jeśli chodzi o sprawdzanie poprawności html, możesz zrobić to wszystko z klasami lub atrybutami z prefiksem danych - chociaż muszę przyznać , to prawda, nie obchodzi mnie: P –

Powiązane problemy