Sinopse
Um padrão de mediador padrão aplicado a AngularJS que não usa $broadcast
s ou $emit
s.
- Evita injetar e expor desnecessariamente
$scope
a visão ondecontrollerAs
for preferível. - Contorna o uso de
$rootScope
para atualizar os modelos de visão existentes nos$scope
caminhos irmãos . - Não aciona ciclos
$apply
ou adicionais$digest
. - Emprega lodash para melhor desempenho entre navegadores.
Mediator.subscribe
retorna uma função para cancelar o registro do assinante, semelhante à$scope.$on
implementação do Angular .
( function( angular , _ ) {
function MediatorService( $log ) {
var Mediator = {};
var channels = {};
var subscriberId = 0;
Mediator.publish = function( channel , publisher , data ) {
if ( ! hasSubscriber( channel ) ) {
return;
}
var subscribers = channels[ channel ];
_.map( subscribers, function( subscriber ) {
try {
subscriber.callback( data );
} catch ( e ) {
$log.error( e , publisher , subscriber.name )
}
} );
};
Mediator.subscribe = function( channel , subscriber , callback ) {
if ( ! hasSubscriber( channel ) ) {
channels[ channel ] = [ ];
}
channels[ channel ].push( {
"callback" : callback ,
"name" : subscriber ,
"subscriberId" : ++subscriberId
} );
return function( ) {
unsubscribe( subscriberId );
};
};
function hasSubscriber( channel ) {
return _.has( channels , channel );
}
function unsubscribe( subscriberId ) {
channels = _.map( channels , function( channel ) {
return _.filter( channel , function( subscriber ) {
return subscriber.subscriberId !== subscriberId;
});
});
}
return Mediator;
}
angular
.module( "app" )
.factory( "Mediator" , [ "$log" , MediatorService ] );
} ) ( angular, _ );
Implementação
HTML
<div data-first=""></div>
<div data-second=""></div>
JS
angular
.module( "app" , [ ] )
.factory( "Mediator" , [ "$log", MediatorService ] )
.directive( "first" , function( ) {
return {
controller: function( ) {
this.name = "First";
},
controllerAs: "first",
template: "<p ng-bind='first.name'></p><div data-third></div>"
};
} )
.directive( "second" , function( Mediator ) {
return {
controller: function( ) {
this.name = "Second";
this.publishNewName = Mediator.publish.bind( this , "NewName" , "second" , this.name );
},
controllerAs: "second",
template: "<a ng-bind='second.name' ng-click='this.publishNewName( )'></a>"
};
} )
.directive( "third" , function( Mediator ) {
return {
controller: function( ) {
this.name = "Third";
var unsubscribe = Mediator.subscribe( "NewName" , "third" , setName.bind( this ) );
function setName(name) {
this.name = name;
unsubscribe( );
}
},
controllerAs: "third",
template: "<p ng-bind='third.name'></p>"
};
} );