2013-04-09 11 views
13

Angular ci fornisce un meccanismo per scrivere le direttive - che è estremamente potente in ciò che può fare. Ma la cosa che continuo a chiedermi è - in quale scenario dovresti effettivamente scrivere una tua direttiva personalizzata.Quando scrivere una direttiva?

Continuiamo a vedere le domande dentro e intorno a Stack Overflow con varie persone che tentano di scrivere direttive che (a mio parere) non devono necessariamente essere scritte in primo luogo. Nella maggior parte dei casi possono essere risolti con una combinazione di ripetizione, commutazione e visualizzazione. Vedi esempi di domande contenenti direttive che penso non dovrebbero essere le direttive in primo luogo!

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

Alcuni scenari esempi. Non li sto prendendo in considerazione in ogni caso ... perché sono sicuro che non è chiaro a nessuno quando dovremmo usare/scrivere una direttiva.

Vediamo lo scenario in cui le persone utilizzano le direttive come meccanismo per il template. È questo il modo giusto di fare le cose? O c'è un modo migliore? (ng-include forse?) Ci sono dei lati positivi/negativi nell'usare le direttive come un meccanismo di template? La ragione di questa domanda è che a volte mi chiedo se le persone scrivono direttive perché provengono dal mondo jquery la prima cosa a cui pensano è scrivere DOM manipolando il codice e poiché la modalità Angolare è non manipolare il DOM nei controller, tutto ciò grava sulla scrittura tutto quel codice in una direttiva.

EDIT:

Credo che questa confusione (di spintoni le cose all'interno di una direttiva) deriva dal fatto angolare non ha una nozione separata di una "vista" - a differenza di Backbone (che ha solo una "vista", ma nessun componente!). Le direttive sono sorprendenti nel definire i componenti - Ma penso che se le usi per creare "viste", perderai parte del modo "angolare". Questa è la mia opinione però - ecco perché sto sollecitando ciò che pensa il resto della comunità angolare.

Il bello delle direttive più semplici (direttive che fanno solo 1 cosa!) È che sono assolutamente facili da testare. Se guardi tutte le direttive, tutti fanno 1 cosa e fanno quella cosa abbastanza bene.

Qual è il modo migliore per definire "viste" riutilizzabili (non componenti!) In Angolare? Dovrebbe essere scritto in una direttiva? O c'è un modo migliore?

Sarebbe fantastico se uno degli Angular Dev avesse un'opinione in proposito!

+1

non appena si desidera eseguire la manipolazione DOM è necessario scrivere una direttiva. I controller non dovrebbero avere una sola manipolazione in essi. Ma la direttiva può avere controller al loro interno. I controller della direttiva – mpm

+0

sono per altri motivi. Quei controller e i normali controller sono diversi. – ganaraj

risposta

10

Beh ... una bella domanda.

Credo che le direttive siano principalmente destinate a "extending HTML so you can build a DSL", migliorando la produttività e la qualità del codice.

La domanda è che questo si ottiene attraverso la componentizzazione delle cose. Ma è di più importante che capiamo che la direttiva non riguarda solo le componenti visive, né solo i modelli, ma anche, sul comportamento.

In sintesi, utilizzando le direttive si potrebbe:

  1. creare un DSL per aumentare gli elementi comportamento
  2. creare widget DSL, in modo da poter smettere di ripetere se stessi
  3. avvolgimento già componenti esistenti, comprando la tua produttività.
  4. ottimizzazione

Aumentare il comportamento non è altro che componentizing comportamento. ng-click, ad esempio, aggiunge il comportamento selezionabile a qualsiasi elemento. Immagina di creare un'app con dozzine di elementi trascinabili. Di quanto si creerebbe una direttiva per aumentare il comportamento degli elementi, rendendola trascinabile senza nemmeno toccare l'elemento visivo (<span draggable>Test</span>). Ancora un altro esempio, immagina di avere suggerimenti speciali sul passaggio del mouse. L'attributo title non è adatto a questo, quindi puoi creare il tuo attributo my-title, che crea automaticamente il tuo "suggerimento speciale" al passaggio del mouse (<span my-title="Some caption">Test</span>).

E quando si sviluppa un'app, si hanno molti concetti e comportamenti specifici del dominio. StackOverflow, ad esempio, ha un forte concetto di voto. Puoi votare su/giù domande, risposte, commenti ... Quindi potresti creare una direttiva riutilizzabile votable, che aggiungerebbe "voto di comportamento" e "vota widget" (frecce su/giù) per rendere pratico qualsiasi elemento.

Quest'ultimo ci dà un'altra faccia: i modelli. Non solo per quelli pigri, ma per migliorare la qualità del codice e la manutenzione dopo il DRY principle. Se si sta ripetendo il codice del controller, la struttura HTML o qualsiasi altra cosa, perché non utilizzare il template e la componentizzazione, giusto? La direttiva è il tuo ragazzo per questo lavoro.

Naturalmente, si dispone anche di un'applicazione generica di direttive. Molte applicazioni (per non dire tutte) si basano su elementi cliccabili, questo è il motivo per cui abbiamo un ng-click, per esempio. Molte applicazioni hanno aree di caricamento. E cosa faresti in un modo di pensare jQuery? Dovresti creare un plugin jQuery. Destra? In Angolare, si creerebbe un Widget angolare (usando le direttive). Potresti anche racchiudere un plug-in già esistente utilizzando una direttiva e, ancora una volta, aumentando il suo comportamento in modo che possa comunicare senza problemi con l'applicazione.

Per quanto riguarda plugin di avvolgimento, a tutti i plugin jQuery (ma potrebbe essere MooTools, Ext ...), avete intenzione di creare un controller, chiamano $('element').plugin() su di esso, e la cura che gli eventi jQuery cambiano e $ digerire il cannocchiale per te. Questo è un altro uso perfetto della direttiva. Puoi creare una direttiva che applichi .plugin() sul tuo elemento, ascoltando gli eventi e modificando/digerendo il tuo scope per te. Questo è ciò che è Angular UI Project, dai un'occhiata.

Un ultimo punto è l'ottimizzazione. Di recente ho creato e app che crea tabelle con colonne e righe dinamiche (una griglia). La domanda è che i dati vengano aggiornati in tempo reale! E la ng-repeat all'interno di ng-repeat, per creare intestazioni, stava uccidendo le prestazioni delle applicazioni (cicli annidati in ogni ciclo $apply, che avvenivano ogni mezzo secondo). Quindi puoi creare una direttiva che crea il modello di colonne e utilizzare ancora ng-repeat al suo interno, ma avresti un ciclo attraverso le colonne solo sulla versione di colonne.

Quindi, concludendo, credo che le direttive sono circa componentizing comportamento e la forma (template), che si acquista producitivity e codice di qualità.

2

Io personalmente scrivo parecchie direttive perché tendono a rendere il mio programma molto più dichiarativo.

Un esempio: in un JSON -> modulo HTML parser che ho fatto di recente, ho creato una direttiva "form-elemento", che analizza l'elemento JSON una creazione delle direttive necessarie come è bambini. In questo modo ho una direttiva per ogni tipo di campo, con comportamenti e metodi specifici. Inoltre, qualsiasi comportamento comune condiviso tra tutti gli elementi è nella direttiva form-element.

In questo modo, un elemento di gruppo è una direttiva con una ng-repeat nel suo modello e un elemento titolo è semplice come un h1. Ma tutti possono avere lo stesso comportamento condizionale (un gruppo può apparire solo se un campo precedente ha un certo valore impostato, per esempio).E tutto estremamente pulito - ogni volta che ho bisogno di aggiungere/modificare, tutto rimane perfettamente inserito, e l'HTML è estremamente dichiarativo.

EDIT - incluso uno snippet di codice, come richiesto tramite commenti.

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

quindi lo stai praticamente usando per il template. Questo è un caso d'uso. Se stai andando bene a creare direttive a livello di elemento (il che significa che non ti interessa la convalida html!) Questo è perfettamente a posto. Hai preso in considerazione l'utilizzo di ng-include invece di una direttiva per questo scenario? Naturalmente una direttiva con nome personalizzato è molto più semantica. Ma mi stavo solo chiedendo. Forse la domanda è - è anche possibile fare lo stesso con ng-include! – ganaraj

+0

In alcuni casi (come un semplice h1) potrebbe essere solo un modello, ma certamente non si tratta di elementi più complicati, come un ajax che carica più selezioni con select2 e callback definiti nel JSON :) Non è davvero 'possibile fare la maggior parte di ciò che viene fatto (nel mio caso) in un ng-include, ma anche nei casi in cui lo è, perché farlo? provare a creare strutture estremamente complesse usando solo html sembra un uso eccessivo del sistema di template e ovviamente (e nel caso di h1) sostituirei la mia linea di template inline con una chiamata extra a un file html, il tutto con intestazioni extra . –

+0

(doppio post, scusa) nel mio caso, ng-include significherebbe a) 15+ file html solo per i campi o b) carichi di direttive ng-switch (che sono utili come sono, tendono ad essere piuttosto disordinati) e se io desiderava un comportamento specifico del modello, ovvero il lancio di funzioni su un controller di dump disordinato o la presenza di più di 10 controller, che potevano (e dovevano) essere solo direttive. * (Inoltre, come dovrei notare, averlo tutto-js lo rende facile da usare come widget che è) * Per quanto riguarda la validazione html, puoi fare tutto questo con le classi, o con gli attributi con prefisso dati - anche se devo ammettere , è vero, non mi interessa: P –

Problemi correlati