2012-04-02 15 views
44

En mi proyecto simple tengo 2 vistas: una vista de línea de pedido (marca) y una aplicación. He adjuntado la función que permite seleccionar varios elementos:Backbone JS: ¿se pueden ver las actualizaciones de los disparadores en otras vistas?

 
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 están seleccionados. 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, por lo que si se selecciona más de 1, mostraré un menú para la selección múltiple.

+2

Por cierto, '$ (this.el) .toggleClass ("seleccionado")'. O incluso más corto a 'this.model.selected = $ (this.el) .toggleClass ('selected'). HasClass (" selected ");'. –

Respuesta

71

Es posible que desee tener una lectura de esta discusión de eventos pub/sub Backbone:

http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/

me gustaría añadir que en como mecanismo evento global:

Backbone.pubSub = _.extend({}, Backbone.Events); 

Luego en una vista puede desencadenar un evento:

Backbone.pubSub.trigger('my-event', payload); 

Y en otro se puede escuchar:

Backbone.pubSub.on('my-event', this.onMyEvent, this); 
+0

En realidad, esto es exactamente lo que leo eventualmente http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/ y comenzó a usarlo. Lo bueno. Gracias) –

+0

Esto realmente me ayudó a lo grande. Gracias. – Bharat

+0

Ditto comentar arriba ... muchas gracias! – Alex

1

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 hable 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.

7

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 manera su vista de aplicación no le importa si se trata de un BrandView o FooView que publica el evento 'selected', sólo que el evento ocurrió. Como resultado, considero que es una forma sostenible de administrar eventos entre partes de su aplicación, no solo vistas.

Si sigue leyendo sobre la 'Fachada', puede 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.

+0

¿Es esto compatible nativamente con Backbone? –

+0

No forma parte de Backbone. , es por eso que me gusta. Si tuviera que vincular un evento DOM en una vista directamente a otra vista que sería muy confuso cuando está tratando de cambiar sus puntos de vista. Actualizaré mi respuesta para intentar aclarar a qué me refiero. –

0

Utilice los mismos objetos del 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.

Por lo que permite por lo que tiene algunas marcas que se ha podido ir a través de una colección:

var brands = new Brands([]); 
brands.fetch(); 

Ahora se crea un APPVIEW, y una serie de BrandView de cada modelo.

var appView = new AppView({brands: brands}); 
var brandViews = brands.map(function(brand) { 
    return new BrandView({brand: brand}); 
}); 

El APPVIEW y la brandViews ahora ambos tienen acceso a los mismos objetos del modelo, por lo que cuando cambia uno:

brands.get(0).selected = true; 

Luego se cambia cuando se accede por las vistas que hacen referencia a él también.

console.log(appView.brands.get(0).selected); // true 
console.log(brandViews[0].brand.selected) // true 
+0

sus primeros 2 ejemplos de código ya están en uso. Y sé cómo obtener el número de marcas seleccionadas. La pregunta fue, ¿cómo puede una Vista saber que algo fue seleccionado/deseleccionado en otra Vista? –

0

Igual que John ha sugerido anteriormente, el patrón mediador funciona muy bien en este escenario, como Addy Osmani sumando este tema de nuevo en Backbone fundamentals.

la herida usando el plugin Backbone.Mediator que es simple y grande, y hace que mis módulos AMD Ver trabajar juntos sin problemas =)

1

Aquí es mi caso con una necesidad similar: Backbone listento parecía una solución para redirigir al iniciar sesión página para solicitudes caducadas o no autenticadas.

que añade controlador de eventos a mi router y lo hizo escuchar el evento mundial tales 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 jQuery manejador de error de Ajax:

$(document).ajaxError(
    function(event, jqxhr, settings, thrownError){ 
     ....... 
     if(httpErrorHeaderValue==="some-value"){ 
      Backbone.trigger("auth:not-authenticated",errMsg); 
     } 
    });  
+0

En un lugar donde Backbone.on() no funcionaría this.listenTo() funcionó ... –

1

Puede utilizar Backbone objeto como el bus de eventos.

Este enfoque es un poco más limpio pero todavía se basa en el objeto Global Backbone aunque

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. 
    } 

}); 
Cuestiones relacionadas