javascript - template - backbonejs github
Backbone.js state management/view initialization basado en fragmento de url (2)
Estoy tratando de hacer un seguimiento del estado en esta aplicación usando Backbone.js:
Tengo un "ChartAppModel" con un conjunto de valores predeterminados:
ChartAppModel = Backbone.Model.extend({
defaults: {
countries : [],
selectedCountries : [],
year : 1970,
},
initialize: function() {
loadAbunchOfData();
checkStartState();
}
});
Sin embargo, si se le asigna un fragmento de inicio, este estado predeterminado debe sobrescribirse:
var startState = $.deparam.fragment(); //using Ben Alman''s BBQ plugin
this.set({selectedCountries: startState.s, year: startState.y});
Ahora, por ejemplo, SidebarView está listo para actualizarse:
ChartAppViewSidebar = Backbone.View.extend({
initialize: function(){
this.model.bind("change:selectedCountries", this.render);
},
render : function(){
[... render new sidebar with check boxes ...]
},
El problema es que también tengo un controlador de eventos en la barra lateral que actualiza el modelo:
events: {
"change input[name=country]": "menuChangeHandler",
},
menuChangeHandler : function(){
[... set selectedCountries on model ...]
},
Entonces habrá un ciclo de retroalimentación ... Y luego, también me gustaría una forma de impulsar un nuevo estado, así que escucho los cambios del modelo:
ChartAppModel = Backbone.Model.extend({
initialize: function() {
this.bind("change", this.setState);
}
});
... y relativamente pronto este administrador de estado colapsará ...
Preguntas:
1) ¿Cómo inicio mis vistas (por ejemplo, "qué casillas de verificación deben verificarse") según el fragmento? (Se aprecian sugerencias sobre las mejores prácticas para el estado / estado de inicio que no es una "ruta" típica)
2) ¿Cómo puedo evitar que mis vistas configuren un atributo en el modelo que ellos mismos escuchan?
3) ¿Cómo puedo presionar un nuevo estado basado en una parte del modelo?
Bonificación :)
4) ¿Cómo describirías el código de la aplicación descrita?
¡Gracias!
2) ¿Cómo puedo evitar que mis vistas configuren un atributo en el modelo que ellos mismos escuchan?
Tu no Su modelo debería estar validando cualquier atributo que trate de actualizar para que su vista necesite escuchar en caso de que falle la configuración del atributo o la validación cambie el valor.
Lo que hace su vista es intentar establecer un valor en el modelo, luego el modelo lo establece, cambia los datos y lo establece o lo rechaza. Su vista debe actualizarse en consecuencia.
3) ¿Cómo puedo presionar un nuevo estado basado en una parte del modelo?
// for each attribute
_.each(["attribute1", "attribute2", "attribute3", ...], _.bind(function(val) {
// bind the change
// bind the setState with `this` and the `value` as the first parameter
this.bind("change:" + value, _.bind(this.setState, this, value));
}, this));
Esa es una pregunta bien definida!
Hay una pregunta sobre qué es un modelo. Creo que hay una definición que flota en torno a lo que constituye un modelo en el mundo de la red troncal, y no estoy seguro de que su estrategia esté de acuerdo con esa definición. También está almacenando el estado tanto en la url como en el modelo. Puedes simplemente almacenar el estado en la url, como explicaré.
Si estuviera haciendo esto, habría 2 vistas. Uno para los controles de su aplicación, y anidado dentro de ese para su gráfico: GraphView y AppView. El modelo será la información que va a trazar, no el estado de la interfaz.
Use un controlador para iniciar la vista de la aplicación y también para procesar cualquier estado de interfaz definido en la url.
Hay una pregunta sobre las palancas de estado en Backbone. Las aplicaciones web tradicionales usaban un enlace / url como palanca principal de estado, pero ahora todo eso está cambiando. Aquí hay una posible estrategia:
Checkbox Change Event -> Update location fragment -> trigger route in controller -> update the view
Slider Change Event -> Update location fragment -> trigger route in controller -> update the view
Lo mejor de una estrategia de este tipo es que se ocupa del caso en el que las URL se pasan o se marcan como favoritos.
Url specified in address bar -> trigger route in controller -> update the view
Haré una puñalada en un ejemplo de pseudo código. Para esto, haré algunas suposiciones sobre los datos: los datos son la población de perros a lo largo del tiempo (con una granularidad del año), donde el control deslizante debe tener un límite inferior y superior, y los datos del volumen son demasiado grandes para cargarlo todo al cliente de una vez
Primero veamos el Modelo para representar los datos estadísticos. Para cada punto del gráfico, necesitamos algo como {población: 27000, año: 2003} Permite representar esto como
DogStatModel extends Backbone.Model ->
y una colección de estos datos será
DogStatCollection extends Backbone.Collection ->
model: DogStatModel
query: null // query sent to server to limit results
url: function() {
return "/dogStats?"+this.query
}
Ahora veamos el controlador. En esta estrategia que propongo, el controlador hace honor a su nombre.
AppController extends Backbone.Controller ->
dogStatCollection: null,
appView: null,
routes: {
"/:query" : "showChart"
},
chart: function(query){
// 2dani, you described a nice way in your question
// but will be more complicated if selections are not mutually exclusive
// countries you could have as countries=sweden;france&fullscreen=true
queryMap = parse(query) //
if (!this.dogStatCollection) dogStatCollection = new DogStatCollection
dogStatCollection.query = queryMap.serverQuery
if (!this.appView) {
appView = new AppView()
appView.collection = dogStatCollection
}
appView.fullScreen = queryMap.fullScreen
dogStatCollection.fetch(success:function(){
appView.render()
})
}