2012-02-22 14 views
19

Ho un app spina dorsale con una struttura vista che appare come il seguente - notare che ho implementazioni rimossi, modelli, collezioni, ecc per brevità:Come posso "bollire" gli eventi in una gerarchia di Backbone View?

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(); 

    } 

}); 

In sostanza, ogni volta che la funzione 's il FilterViewtoggleFilter() viene chiamato, vorrei attivare un evento chiamato filtered o qualcosa del genere che viene poi catturato dallo NewsListView, che quindi chiama la sua funzione reset(). Senza passare un riferimento di un oggetto NewsListView al mio FilterView, non sono sicuro di come inviarlo un evento. Qualche idea?

risposta

0

Quindi, ho trovato una soluzione: creare un oggetto che si estende Backbone.Events e passarlo come parametro a più viste. Questo sembra quasi un messaggio che passa tra attori, o qualcosa del genere. Ad ogni modo, sto postando questa risposta come risposta nel caso in cui qualcun altro abbia bisogno di una soluzione rapida, ma non accetterò la risposta. Questo sembra hacky. Mi piacerebbe ancora vedere una soluzione migliore.

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

Questo problema può essere risolto utilizzando il piccolo backbone.js mod. Semplicemente modificare Backbone.Events.trigger per il passaggio di eventi al this.parent

if this.parent != null 
3

Si potrebbe essere in grado di farlo utilizzando la funzionalità già disponibile degli eventi jquery e della proprietà degli eventi backbone.

Ad esempio, invece di fare questo da dentro la tua visualizzazione secondaria:

this.trigger("yourevent", this); 

fare questo, invece:

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

Poi in qualsiasi visualizzazione che è un genitore, nonno, ecc del vostro Bambini , ascolta l'evento sul $ el di quella vista definendo una proprietà sull'oggetto eventi di quella vista:

events:{ 
    "yourevent":"yourhandler" 
} 

e definire il gestore su quella vista così:.

yourhandler:function(subview) { 
} 

Quindi in questo modo, la vista non ha bisogno di sapere su ciò che esistono vista discendente, solo il tipo di evento che è interessato a Se la vista di origine l'evento viene distrutto, non è necessario modificare nulla nella vista degli antenati. Se la vista dell'antenato viene distrutta, Backbone staccherà automaticamente i gestori.

Attenzione: non ho ancora provato questo, quindi ci può essere un gotcha lì da qualche parte.

+0

Questo non ha funzionato per me. – anyaelise

+0

Grazie per l'aha! momento. –

0

Il modo più semplice che ho trovato per attivare e ascoltare gli eventi consiste semplicemente nell'utilizzare l'oggetto Backbone stesso.Ha già gli eventi funzioni miste ad esso, in modo da poter semplicemente scatenare esempio:

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

poi, in qualsiasi altra vista dorsale nella vostra applicazione, è possibile ascoltare per questo evento ad esempio:

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

Non sono esattamente sicuro di quale sia il vantaggio nel non utilizzare l'oggetto Backbone come gestore di eventi e invece di creare un oggetto separato per farlo, ma per un lavoro rapido e sporco, quanto sopra funziona correttamente. HTH!

NOTA: uno svantaggio di questo è che ogni ascoltatore "sente" ogni singolo evento innescato in questo modo. Non sei sicuro di quale sia il grosso O, ma stai attento a non sovraccaricare le tue visualizzazioni con molte di queste cose. Ancora: questo è veloce e sporco! :)

Problemi correlati