2012-02-22 16 views
19

Tengo una aplicación columna vertebral con una estructura de vista que se parece a la siguiente - en cuenta que he implementaciones retirados, modelos, colecciones, etc. por razones de brevedad:¿Cómo puedo "burbujear" eventos en una jerarquía de Vista Backbone?

NewsListView = Backbone.View.extend({ 

    el: $('li#newspane'), 

    // This is what I would like to be able to do 
    // events: { 'filtered': 'reset' } 

    initialize: function() { 
     _.bindAll(this); 
    }, 

    render: function() { 
    }, 

    reset: function(){ 
    } 

}); 

FilterView = Backbone.View.extend({ 

    el: $('li.filter'), 

    initialize: function() { 
    }, 

    render: function() { 
    }, 

    toggleFilter: function() { 
    } 

}); 

AllView = Backbone.View.extend({ 

    initialize: function() { 

     this.newsListView = new NewsListView(); 
     this.filterView = new FilterView(); 

    } 

}); 

Esencialmente, cada vez que toggleFilter() función de la FilterView 's se llama, me gustaría despedir un evento llamado filtered o algo así que luego es capturado por el NewsListView, que luego llama a su función reset(). Sin pasar una referencia de un objeto NewsListView a mi FilterView, no estoy seguro de cómo enviar un evento. ¿Algunas ideas?

Respuesta

0

Entonces, se me ocurrió una solución: crear un objeto que extienda Backbone.Events, y pasarlo como un parámetro a múltiples vistas. Esto casi parece un mensaje que pasa entre los actores, o algo así. De todos modos, estoy publicando esto como una respuesta en caso de que alguien más necesite una solución rápida, pero no voy a aceptar la respuesta. Esto se siente hacky. Todavía me gustaría ver una mejor solución.

NewsListView = Backbone.View.extend({ 
    el: $('li#newspane'), 

    // Too bad this doesn't work, it'd be really convenient 
    // events: { 'filtered': 'reset' } 

    initialize: function() { 
     _.bindAll(this); 
     // but at least this does 
     this.options.eventProxy.bind('filtered', this.reset); 
    }, 
    render: function() {}, 
    reset: function() {} 
}); 

FilterView = Backbone.View.extend({ 
    el: $('li.filter'), 

    initialize: function() {}, 
    render: function() {}, 
    toggleFilter: function() { 
     this.options.eventProxy.trigger('filtered'); 
    } 
}); 

AllView = Backbone.View.extend({ 
    initialize: function() { 
     var eventProxy = {}; 
     _.extend(eventProxy, Backbone.Events); 
     this.newsListView = new NewsListView({eventProxy: eventProxy}); 
     this.filterView = new FilterView({eventProxy: eventProxy}); 
    } 
}); 
0

Este problema se puede resolver usando el pequeño backbone.js hack. Simplemente modifique Backbone.Events.trigger para pasar eventos a la this.parent

if this.parent != null 
3

Usted puede ser capaz de hacer esto usando la funcionalidad ya disponible de los eventos jquery y la propiedad de eventos troncales.

Por ejemplo, en lugar de hacerlo desde el interior de su subvista:

this.trigger("yourevent", this); 

hacer esto en su lugar:

this.$el.trigger("yourevent", this); 

Luego, en cualquier punto de vista que es un padre, abuelo, etc de su niño, vista , escuche el evento en $ el de esa vista definiendo una propiedad en el objeto de eventos de esa vista:

events:{ 
    "yourevent":"yourhandler" 
} 

y definir el manejador de ese punto de vista, así:.

yourhandler:function(subview) { 
} 

Así de esta manera, una visión no necesita saber acerca de lo que existen puntos de vista descendientes, sólo el tipo de evento que está interesado en Si la vista se origina el evento se destruye, nada tiene que cambiar en la vista del antepasado. Si se destruye la vista ancestro, Backbone separará los manejadores automáticamente.

Advertencia: Todavía no lo he probado, por lo que puede haber un problema en algún lado.

+0

Esto no funcionó para mí. – anyaelise

+0

¡Gracias por aha! momento. –

0

La manera más fácil que he encontrado para activar y escuchar eventos es simplemente usar el objeto Backbone en sí.Ya cuenta los acontecimientos funciones mezclan a ella, por lo que sólo se puede desencadenar por ejemplo:

Backbone.trigger('view:eventname',{extra_thing:whatever, thing2:whatever2}); 

entonces, en cualquier otro punto de vista la columna vertebral en su aplicación, se puede detectar este evento por ejemplo:

Backbone.on('view:eventname', function(passed_obj) { 
    console.log(passed_obj.extra_thing); 
}); 

No estoy seguro de cuál es la ventaja de no utilizar el objeto Backbone como su controlador de eventos, y en su lugar crear un objeto separado para hacerlo, pero para el trabajo rápido y sucio, lo anterior funciona bien. HTH!

NOTA: una desventaja de esto es que cada oyente "oirá" cada uno de los eventos activados de esta manera. No estoy seguro de cuál es la gran O en eso, pero trabaje con cuidado para no sobrecargar sus puntos de vista con muchas de estas cosas. De nuevo: ¡esto es rápido y sucio! :)

Cuestiones relacionadas