2015-10-24 13 views
10

Sto cercando di capire qual è il miglior approccio GENERICO per comunicare tra direttiva padre e figlio con ambiti isolati (potrebbero essere oggetti riutilizzabili).

significa che se direttiva bambino ha bisogno di aggiornare la direttiva genitore in qualche modo (entrambi hanno isolato scopi), devo passare una funzione di callback:

esempio:

.directive('filterReviewStepBox', function() { 
    return { 
     restrict: 'EA', 
     scop: { 
      //some data 
     }, 
     template: '<div>text<reusable-dir></reusable-dir call-back="foo"></div>', 
     link: function (scope, elem, attrs) { 
      scope.foo = function() { 
       console.log('bar'); 
      }; 
     } 
    }; 
}).directive('reusableDir', function() { 
    return { 
     restrict: 'EA', 
     scope: { 
      callBack: '=callBack' 
       //other data 
     }, 
     template: '<div>text<button type="button" ng-click="bar"></button></div>', 
     link: function (scope, elem, attrs) { 
      scope.bar = function() { 
       scope.callBack(); 
      } 
     } 
    }; 
}); 

o dovrei usare $ emettere():

es:

directive('filterReviewStepBox', function() { 
     return { 
      restrict: 'EA', 
      scope: { 
       // some data 
      }, 
      template: '<div>text<reusable-dir></reusable-dir></div>', 
      link: function (scope, elem, attrs) { 
       scope.$on('foo', function() { 
        console.log('bar'); 
       }); 
      } 
     }; 
    }).directive('reusableDir', function() { 
     return { 
      restrict: 'EA', 
      scope: { //some data 
      }, 
      template: '<div>text<button type="button" ng-click="bar"></button></div>', 
      link: function (scope, elem, attrs) { 
       scope.bar = function() { 
        scope.$emit('foo'); 
       }; 
      } 
     }; 
    }); 

Sento che emettono sarebbe più facile da capire su scala più ampia, ma preoccupato per le prestazioni e le spese generali, ma Im ancora incerto

provato a cercare il miglior approccio online, ma Im ancora calpestati

EDIT

ho dimenticato il

richiedere

opzione. ma non sono ancora sicuro che questa sia la soluzione più corretta. Dato che questo non mi permette di riutilizzare il bambino o il nipote e il tipo di rende la direttiva un oggetto monouso.

+0

c'è l'opzione 'require' che consente di accedere controllore di un'altra direttiva. questo dovrebbe consentire di fare ciò che vuoi. – ieaglle

+0

Vedo cosa stai dicendo ... non ci ho pensato ... ma cosa succede se voglio che il bambino sia riutilizzabile? allora il tuo approccio non può essere usato. –

+0

Vedere la mia modifica –

risposta

0

Per questo scopo, il migliore è utilizzare l'attributo "richiede".

Guida completa alle direttive dirci questa storia richiede attributo: https://docs.angularjs.org/api/ng/service/ $ compilare

Richiede un'altra direttiva e iniettare il suo controller come il quarto argomento della funzione di collegamento. Il richiedono prende un nome di stringa (o array di stringhe), della direttiva (s) per passare in.

Richiede solo racconta la direttiva dovrebbe cercare qualche direttiva madre e prendere il suo controllore. Puoi dire alla direttiva di cercare negli elementi parent con il prefisso ^ e dire se questo requisito è facoltativo con ? prefisso.

Ho modificato il tuo esempio, quindi reusableDir può chiamare filterReviewStepBox controller, ma può anche essere usato da solo.

http://jsbin.com/gedaximeko/edit?html,js,console,output

angular.module('stackApp', []) 
.directive('filterReviewStepBox', function() { 
     return { 
      restrict: 'EA', 
      scope: { 
       // some data 
      }, 
      template: '<div>text<reusable-dir></reusable-dir></div>', 
      link: function (scope, elem, attrs) { 

      }, 
      controller : function() { 
       this.notify = function(value) { 
       console.log('Notified : ' + value); 
       };    
      }, 
      controllerAs: 'vm', 
      bindToController: true 
     }; 
    }).directive('reusableDir', function() { 
     return { 
      restrict: 'EA', 
      scope: { //some data 
      }, 
      require: '?^filterReviewStepBox', 
      template: '<div>text<button type="button" ng-click="bar()"></button></div>', 
      link: function (scope, elem, attrs, controller) { 
       scope.bar = function() { 
        if (controller) { 
        controller.notify('foo'); 
        } 
       }; 
      } 
     }; 
    }); 
+0

la soluzione utilizza l'opzione controller, ma anche questo non risolve il mio problema per direttive generiche che non possono prevedere il controllore genitore che è esattamente il motivo per cui ho posto questa domanda. qui o definisco un controller rigoroso o nessuno, questo non funzionerà su più controller, il che significa che non puoi usarlo con controller1 e poi con controller2, questo è il motivo per cui ho preferito usare $ emit o callback poiché possono essere implementati genericamente. –

+0

Se vuoi dire che come direttiva non sa chi chiama, quindi $ emettere sarebbe davvero più generale. Non userei callback, perché di solito utilizzo transclude, quindi il mio reusableDir non sarebbe all'interno del modello del genitore. Ma come intendevi che non ti permette di riutilizzare "figlio o nipoti"? –

+0

quando si utilizza richiedono che si sia effettivamente obbligati a utilizzare il controller padre o nonno, quindi se voglio utilizzare la funzionalità e la richiamata in un controller diverso non posso ... Personalmente sono più attratto verso $ emit che callBacks ma sto solo cercando di capire la migliore pratica –

0

penso che non è solo la prestazione, è necessario anche prendere qualche fattori in considerazione dalla progettazione e manutenzione prospettiva.

  1. metodo di callback: Questo è forse l'opzione più efficiente. La direttiva figlio chiamerebbe solo un metodo di direttiva padre, senza costi di gestione . Ci sono alcune opzioni spiegate qui: https://stackoverflow.com/a/27997722/2889528

  2. Emit (o per quella trasmissione materia): Questo metodo pubblica l'evento a tutti i $ portata (s) verso l'alto (emettono) o verso il basso (broadcast) alla gerarchia , relativamente costoso, ma ti dà una certa flessibilità per guardare e gestire l'evento ovunque sia disponibile $ scope.

  3. Servizio comune iniettabile: questa opzione può essere utilizzata quando si desidera chiamare un metodo in cui $ scope non è disponibile. Tuttavia, ha creato una stretta dipendenza dal servizio. Questo è più di un progetto pub-sub .

1

Personalmente, cerco di evitare di generare i miei eventi personalizzati. Soprattutto perché è incredibilmente facile provocare propagazioni indesiderate di eventi o bolle (spesso causando digest indesiderati di scope), ma anche a causa del "rumore" sistematico che nelle applicazioni più grandi può diventare molto difficile da gestire.

Le mie opinioni personali a parte, però, e se si tratta di un approccio più "a prova di futuro" che si sta cercando, l'approccio di callback è di gran lunga il più sicuro. Ecco perché ...

  • Angular2 incoraggia gli sviluppatori a esporre onChange attributi da direttive e componenti che dipendono da comunicazione del bambino-to-genitore. Si noti che queste non sono altro che funzioni vincolate e dovrebbero essere definite di conseguenza nei collegamenti o negli ambiti del componente o della direttiva indicati.
  • Simile a quanto sopra, Angular2 documenta un metodo ngOnChanges che può essere definito da qualsiasi controller che desidera sottoscrivere le modifiche ai suoi binding. Se fornito, questo metodo viene chiamato prima che avvenga qualsiasi manipolazione DOM (con i nuovi valori associati), quindi è un candidato perfetto per una comunicazione più "generale" da padre a figlio rispetto all'attuale implementazione di AngularJS $scope.$watch.

Tuttavia, ciò che non è stato menzionato è che la comunicazione tramite i servizi è ancora consigliata, sia in AngularJS che in Angular2.


Problemi correlati