p.s Pre .: He hecho una esencia para usted con el código que escribí a continuación: https://gist.github.com/2863979
Estoy de acuerdo con el pub/sub ('patrón Observer') que se sugiere por las otras respuestas. Sin embargo, también usaría el poder de Require.js junto con Backbone.
¡Addy Osmani ha escrito algunos EXCELENTES! recursos sobre patrones de diseño Javascript y sobre la construcción de aplicaciones de red troncal:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/ http://addyosmani.com/writing-modular-js/ http://addyosmani.github.com/backbone-fundamentals/
Lo bueno de usar AMD (implementado en Require.js) junto con Backbone es que a resolver algunos problemas que usted' d normalmente tiene.
Normalmente definirá clases y almacenarlos en una especie de forma de espacios de nombres, por ejemplo:
MyApp.controllers.Tasks = Backbone.Controller.extend({})
Esto está bien, siempre y cuando se define la mayoría de las cosas en un solo archivo, cuando se inicia la adición de más y más diferentes archivos a la mezcla se vuelve menos robusto y debe comenzar a prestar atención a cómo se carga en diferentes archivos, controllers\Tasks.js
después de models\Task.js
etc. Por supuesto, puede compilar todos los archivos en el orden correcto, etc., pero está lejos de ser perfecto.
Además de esto, el problema con el modo no AMD es que tiene que anidar Vistas dentro de la otra con más fuerza. Digamos:
MyApp.classes.views.TaskList = Backbone.View.extend({
// do stuff
});
MyApp.views.App = Backbone.View.extend({
el: '#app',
initialize: function(){
_.bindAll(this, 'render');
this.task_list = new MyApp.classes.views.TaskList();
},
render: function(){
this.task_list.render();
}
});
window.app = new MyApp.views.App();
Todo bien y bien, pero esto puede convertirse en una pesadilla.
Con AMD puede definir un módulo y darle un par de dependencias, si usted está interesado en cómo funciona este leen los enlaces de arriba, pero el ejemplo anterior sería el siguiente:
// file: views/TaskList.js
define([], function(){
var TaskList = Backbone.View.extend({
//do stuff
});
return new TaskList();
});
// file: views/App.js
define(['views/TaskList'], function(TaskListView){
var App = Backbone.View.extend({
el: '#app',
initialize: function(){
_.bindAll(this, 'render');
},
render: function(){
TaskListView.render();
}
});
return new App();
});
// called in index.html
Require(['views/App'], function(AppView){
window.app = AppView;
});
en cuenta que en el caso de puntos de vista que le devuelven instancias, voy a hacer esto colecciones también, pero para los modelos que me gustaría volver clases:
// file: models/Task.js
define([], function(){
var Task = Backbone.Model.extend({
//do stuff
});
return Task;
});
esto puede parecer un poco mucho al principio, y la gente puede pensar 'wow esto es excesivo '. Pero el verdadero poder se hace evidente cuando se tiene que utilizar los mismos objetos en muchos módulos diferentes, por ejemplo, las colecciones:
// file: models/Task.js
define([], function(){
var Task = Backbone.Model.extend({
//do stuff
});
return Task;
});
// file: collections/Tasks.js
define(['models/Task'], function(TaskModel){
var Tasks = Backbone.Collection.extend({
model: TaskModel
});
return new Tasks();
});
// file: views/TaskList.js
define(['collections/Tasks'], function(Tasks){
var TaskList = Backbone.View.extend({
render: function(){
_.each(Tasks.models, function(task, index){
// do something with each task
});
}
});
return new TaskList();
});
// file: views/statistics.js
define(['collections/Tasks'], function(Tasks){
var TaskStats = Backbone.View.extend({
el: document.createElement('div'),
// Note that you'd have this function in your collection normally (demo)
getStats: function(){
totals = {
all: Tasks.models.length
done: _.filter(Tasks, function(task){ return task.get('done'); });
};
return totals;
},
render: function(){
var stats = this.getStats();
// do something in a view with the stats.
}
});
return new TaskStats();
});
Nota ese objeto las 'tareas' es exactamente la misma en ambos puntos de vista, por lo que los mismos modelos, estado, etc. Esto es mucho mejor que tener que crear instancias de la colección Tareas en un punto y luego hacer referencia a ella a través de toda la aplicación todo el tiempo.
Al menos para mí el uso de Require.js con Backbone me ha quitado una pieza gigantesca del enigma con dónde crear una instancia de qué. Usar módulos para esto es muy útil. Espero que esto sea aplicable a su pregunta también.
p.s. tenga en cuenta que también incluiría Backbone, Underscore y jQuery como módulos en su aplicación, aunque no es necesario, puede cargarlos utilizando las etiquetas de script normales.
es posible que desee comprobar Marionette por la misma razón @Luc Perkins sugirió Backbone Aura. Marionette puede ser un poco más maduro que Aura –
Creo que TaskCreateView y TaskPaneView son innecesarios. TaskCreateView, en particular, no debería estar allí, ya que no tiene ningún modelo para representar. Incorpore la creación de tareas en TaskListView. Tal vez un control de entrada que permita a los usuarios agregar nuevas tareas. Y cuando el usuario presione la tecla Entrar, agréguelo a la colección Tareas. Estoy asumiendo que está escuchando para agregar eventos en la colección, para que pueda agregar el TaskView recién creado al TaskListView. Puede mostrar TaskListView siempre que el usuario se enfoque en WidgetView. – Vishal