Ecco un paio di possibilità.
1. centralizzate: negozio ClosedTune
oggetti nel TuneBook
esempio
memorizzare un riferimento a ciascun ClosedTune
in tune_book.tunes
. Come si popola tune_book.tunes
dipende da voi; dal momento che hai menzionato un metodo di aggiunta su TuneBook
, questo è quello che ho illustrato di seguito.
Nel gestore TuneBook
eventi, recuperare il ClosedTune
da tune_book.tunes
usando qualcosa come l'attributo id
del target dell'evento come la chiave. Quindi chiamare il gestore Tune
o ClosedTune
.
http://jsfiddle.net/p5QMT/1/
var Tune = Backbone.View.extend({
className: "tune",
click_handler: function (event) {
event.preventDefault();
console.log(this.id + " clicked");
},
render: function() {
this.$el.html(
'<a href="" class="button">' + this.id + '</a>'
);
return this;
}
});
var ClosedTune = Tune.extend({});
var OpenTune = Tune.extend({
events: {
"click .button" : 'click_handler'
}
});
var TuneBook = Backbone.View.extend({
events: {
"click .tune .button" : 'click_handler'
},
click_handler: function (event) {
var tune = this.options.tunes[
$(event.target).closest(".tune").attr('id')
];
tune.click_handler(event);
},
add_tune: function (tune) {
this.options.tunes[tune.id] = tune;
this.$el.append(tune.render().el);
},
render: function() {
$("body").append(this.el);
return this;
}
});
var tune_book = new TuneBook({
tunes: {}
});
[1, 2, 3].forEach(function (number) {
tune_book.add_tune(new ClosedTune({
id: "closed-tune-" + number
}));
});
tune_book.render();
var open_tune = new OpenTune({
id: "open-tune-1"
});
$("body").append(open_tune.render().el);
2. decentrata: associare l'oggetto vista con l'oggetto DOM utilizzando jQuery.data()
Quando si crea un ClosedTune
, memorizzare un riferimento ad esso, ad esempio, this.$el.data('view_object', this)
.
Nel listener di eventi, recuperare il ClosedTune
, per esempio $(event.target).data('view_object')
.
È possibile utilizzare lo stesso gestore esatta per ClosedTune
(in TuneBook
) e OpenTune
, se si vuole.
http://jsfiddle.net/jQZNF/1/
var Tune = Backbone.View.extend({
className: "tune",
initialize: function (options) {
this.$el.data('view_object', this);
},
click_handler: function (event) {
event.preventDefault();
var tune =
$(event.target).closest(".tune").data('view_object');
console.log(tune.id + " clicked");
},
render: function() {
this.$el.html(
'<a href="" class="button">' + this.id + '</a>'
);
return this;
}
});
var ClosedTune = Tune.extend({
initialize: function (options) {
this.constructor.__super__.initialize.call(this, options);
}
});
var OpenTune = Tune.extend({
events: {
"click .button" : 'click_handler'
}
});
var TuneBook = Backbone.View.extend({
events: {
"click .tune .button": Tune.prototype.click_handler
},
add_tune: function (tune) {
this.$el.append(tune.render().el);
},
render: function() {
$("body").append(this.el);
return this;
}
});
var tune_book = new TuneBook({
tunes: {}
});
[1, 2, 3].forEach(function (number) {
tune_book.add_tune(new ClosedTune({
id: "closed-tune-" + number
}));
});
tune_book.render();
var open_tune = new OpenTune({
id: "open-tune-1"
});
$("body").append(open_tune.render().el);
risposta al commento
Ho considerato l'opzione 1, ma decise di non farlo, come ho già una collezione di modelli sintonizzare la tunebook e non volevo un altro oggetto I' D necessario mantenere la sincronizzazione
Immagino che dipenda da che tipo di gestione/sincronizzazione si sente il bisogno di fare, e perché.
(per esempio in TuneModel.remove() avrei bisogno di togliere la vista dalla lista di tunebook di punti di vista ... probabilmente avrebbe bisogno di eventi per fare questo, quindi un evento unica soluzione comincia a guardare più attraente).
Perché ti senti che è "necessario rimuovere la vista dalla lista di tunebook di punti di vista"? (Non sto suggerendo che non dovresti, solo chiedendo perché tu voglia.) Dato che lo fai, come pensi che l'approccio di @ggozad differisca da questo punto di vista?
Entrambe le tecniche memorizzano gli oggetti ClosedTune
nell'istanza TuneBook
. Nella tecnica di @ggozad è nascosta dietro un'astrazione che forse ti rende meno ovvio.
Nel mio esempio vengono memorizzati in un oggetto JS normale (tune_book.tunes
). In @ ggozad sono memorizzati nella struttura _callbacks
utilizzata da Backbone.Events
.
Aggiunta di un ClosedTune
:
1.
this.options.tunes[tune.id] = tune;
2.
this.on('buttonClick:' + tune.id, tune.handler, tune);
Se si vuole sbarazzarsi di un ClosedTune
(dite la si rimuove dal documento con tune.remove()
e vuoi che l'oggetto vista sia andato completamente), usando l'approccio di @ ggozad lascerai un riferimento orfano allo ClosedTune
i n tune_book._callbacks
a meno che non si esegue lo stesso tipo di servizio di pulizia che avrebbe senso con l'approccio ho suggerito:
1.
delete this.options.tunes[tune.id];
tune.remove();
2.
this.off("buttonClick:" + tune.id);
tune.remove();
La prima riga di ogni esempio è facoltativo - a seconda se si desidera pulire gli oggetti ClosedTune
o meno.
L'opzione 2 è più o meno ciò che sto facendo in questo momento, ma (per altri motivi) memorizzo anche il modello come un attributo di dati in vista. $ El, e non posso fare a meno di pensare che ci sia deve essere un modo migliore di memorizzare i riferimenti dappertutto.
Bene, alla fine si riduce alle preferenze su come strutturare le cose. Se si preferisce archiviare gli oggetti di visualizzazione in modo più centralizzato, è possibile memorizzarli nell'istanza TuneBook
invece di utilizzare jQuery.data
. Vedi n. 1: centralizzato.
un modo o nell'altro sei memorizzare i riferimenti agli oggetti ClosedTune
: utilizzando jQuery.data
, o in un oggetto pianura nel TuneBook
, o in _callbacks
nel TuneBook
.
Se ti piace l'approccio di @ggozad per ragioni che comprendi, prova a farlo, ma non è magico. Dato che è presentato qui non sono sicuro di quale vantaggio debba essere fornito dal livello extra di astrazione rispetto alla versione più semplice che presento in # 1. Se c'è qualche vantaggio, sentitevi liberi di riempirmi.
Se gli eventi verranno eseguiti dai gestori nel modello 'Tune' perché si desidera effettuare la deviazione' ChildView -> ParentView -> Model' .. è possibile eseguire il 'Model.handler' direttamente da' ChildView'. .. In altra parte puoi usare il 'Modello' come messenger: puoi modificare lo stato del Modello da ChildView e lasciare che il ParentView ascolti questa modifica. – fguillen
@fguillen È molto meno efficiente associare gli eventi (forse dovrei essere chiaro, intendo gli eventi DOM piuttosto che gli eventi personalizzati Backbone) al nodo DOM di ogni vista figlia piuttosto che una sola volta al nodo DOM della vista genitore. Sulla tabella di 300 righe generata dal rendimento della mia app è notevolmente lento quando si associa direttamente a ciascuna riga. Quello che mi serve è 'ParentView -> [childView] -> childModel' – wheresrhys