javascript - tutorial - Backbone JS: ¿se pueden ver las actualizaciones de los disparadores en otras vistas?
backbonejs github (7)
Al igual que John ha sugerido anteriormente, el patrón del mediador funciona muy bien en este escenario, ya que Addy Osmani resume este tema nuevamente en los fundamentos del backbone .
Herido utilizando el complemento Backbone.Mediator que es simple y excelente, y hace que mis módulos AMD View funcionen juntos sin problemas =)
En mi proyecto simple tengo 2 vistas: una vista de línea de pedido (marca) y una aplicación. He adjuntado una función que permite seleccionar múltiples elementos:
var BrandView = Backbone.View.extend({ ...some code... toggle_select: function() { this.model.selected = !this.model.selected; if(this.model.selected) $(this.el).addClass(''selected''); else $(this.el).removeClass(''selected''); return this; } }); var AppView = Backbone.View.extend({ ...some code... delete_selected: function() { _.each(Brands.selected(), function(model){ model.delete_selected(); }); return false; }, });
La cosa es, quiero saber cuántos elementos se seleccionan. En esta configuración, la selección NO está afectando al modelo y, por lo tanto, no activa ningún evento. Y desde el concepto de MVC entiendo que las vistas no deberían estar hablando directamente con otras vistas. Entonces, ¿cómo puede AppView saber que se está seleccionando algo en BrandViews?
Y más específicamente, I AppView para saber cuántos elementos se seleccionaron, de modo que si se selecciona más de 1, mostraré un menú para la selección múltiple.
Aquí está mi caso con una necesidad similar: Backbone listenTo parecía una solución para redirigir a la página de inicio de sesión para solicitudes expiradas o no autenticadas.
Agregué controlador de eventos a mi enrutador y lo hice escuchar el evento global como:
Backbone.Router.extend({
onNotAuthenticated:function(errMsg){
var redirectView = new LoginView();
redirectView.displayMessage(errMsg);
this.loadView(redirectView);
},
initialize:function(){
this.listenTo(Backbone,''auth:not-authenticated'',this.onNotAuthenticated);
},
.....
});
y en mi controlador de error jquery ajax:
$(document).ajaxError(
function(event, jqxhr, settings, thrownError){
.......
if(httpErrorHeaderValue==="some-value"){
Backbone.trigger("auth:not-authenticated",errMsg);
}
});
Es posible que desee leer esta discusión sobre Backbone pub / sub events:
Me gusta agregarlo como un mecanismo de evento global:
Backbone.pubSub = _.extend({}, Backbone.Events);
Luego, en una vista puede activar un evento:
Backbone.pubSub.trigger(''my-event'', payload);
Y en otro puedes escuchar:
Backbone.pubSub.on(''my-event'', this.onMyEvent, this);
Ignorando los problemas con esto que ya mencionas en tu publicación, puedes vincular y activar eventos desde / hacia el objeto global Backbone.Event, que permitirá que cualquier cosa se comunique con cualquier otra cosa. Definitivamente no es la mejor solución, y si tiene puntos de vista conversando entre sí, entonces debería considerar refaccionar eso. Pero ya estás! Espero que esto ayude.
Puede usar el objeto Backbone como el bus de eventos.
Este enfoque es algo más limpio, pero aún así se basa en el objeto Global Backbone
var view1 = Backbone.View.extend({
_onEvent : function(){
Backbone.trigger(''customEvent'');
}
});
var view2 = Backbone.View.extend({
initialize : function(){
Backbone.on(''customEvent'', this._onCustomEvent, this);
},
_onCustomEvent : function(){
// react to document edit.
}
});
Use los mismos objetos modelo. AppView podría inicializarse con una colección y BrandView inicializarse con un modelo de esa colección. Cuando los atributos de un objeto de rama cambian, cualquier otro código que tenga una referencia a ese modelo puede leerlo.
Así que permite que tengas algunas marcas que obtengas a través de una colección:
var brands = new Brands([]);
brands.fetch();
Ahora crea un AppView y una matriz de BrandView para cada modelo.
var appView = new AppView({brands: brands});
var brandViews = brands.map(function(brand) {
return new BrandView({brand: brand});
});
AppView y BrandViews ahora tienen acceso a los mismos objetos modelo, por lo que cuando cambias uno:
brands.get(0).selected = true;
Luego cambia cuando se accede por las vistas que también lo hacen referencia.
console.log(appView.brands.get(0).selected); // true
console.log(brandViews[0].brand.selected) // true
Uso lo que Addy Osmani llama el patrón del mediador http://addyosmani.com/largescalejavascript/#mediatorpattern . Vale la pena leer todo el artículo.
Básicamente es un administrador de eventos que le permite suscribirse y publicar eventos. Por lo tanto, su AppView se subindicaría a un evento, es decir, ''seleccionado''. Entonces BrandView publicaría el evento ''seleccionado''.
La razón por la que me gusta es porque te permite enviar eventos entre vistas, sin que las vistas estén directamente unidas.
Por ejemplo
var mediator = new Mediator(); //LOOK AT THE LINK FOR IMPLEMENTATION
var BrandView = Backbone.View.extend({
toggle_select: function() {
...
mediator.publish(''selected'', any, data, you, want);
return this;
}
});
var AppView = Backbone.View.extend({
initialize: function() {
mediator.subscribe(''selected'', this.delete_selected)
},
delete_selected: function(any, data, you, want) {
... do something ...
},
});
De esta forma, a su vista de aplicación no le importa si se trata de un BrandView o FooView que publica el evento ''seleccionado'', solo que ocurrió el evento. Como resultado, considero que es una forma sostenible de administrar eventos entre partes de su aplicación, no solo vistas.
Si lees más sobre la ''Fachada'', puedes crear una buena estructura de permisos. Esto le permitiría decir que solo un ''AppView'' puede suscribirse a mi evento ''seleccionado''. Me parece útil ya que deja muy claro dónde se están utilizando los eventos.