Backbone.js state management / view initialization based on url fragment

前端 未结 2 467
遇见更好的自我
遇见更好的自我 2021-01-31 04:24

I\'m trying to keep track of the state in this app using Backbone.js:

\"enter

I ha

相关标签:
2条回答
  • 2021-01-31 04:40

    That is one well defined question!

    There is a question over what is a model. I believe there is a definition floating around as to what constitutes a model in the backbone world, and I'm not sure your strategy is in keeping with that definition. Also you are storing the state in both the url, and the model. You can just store the state in the url, as I will explain.

    If I was doing this, there would be 2 views. One for your app controls, and nested inside that one for your graph: GraphView, and AppView. The model will be the data your going to plot, not the state of the interface.

    Use a controller to kick start the app view and also to process any interface state defined in the url.

    There is a question about levers of state in Backbone. Traditional web applications used a link/url as the primary lever of state but all that is now changing. Here is one possible strategy:

    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
    

    The great thing about such a strategy is that it takes care of the case where urls are passed around or bookmarked

    Url specified in address bar -> trigger route in controller -> update the view
    

    I'll take a stab at a pseudo code example. For this, I will make some assumptions on the data: The data is the dog population over time (with a granularity of year), where the slider should have a lower and upper bound, and there volume data is too large to load it all to the client at once.

    First let's look at the Model to represent the statistical data. For each point on the graph we need something like { population: 27000, year: 2003 } Lets represent this as

    DogStatModel extends Backbone.Model ->
    

    and a collection of this data will be

    DogStatCollection extends Backbone.Collection ->
        model: DogStatModel
        query: null // query sent to server to limit results
        url: function() {
            return "/dogStats?"+this.query
        }
    

    Now lets look at the controller. In this strategy I propose, the controller lives up to its name.

    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()
            })            
        }
    
    0 讨论(0)
  • 2021-01-31 04:54

    2) How can I avoid my views setting an attribute on the model which they themselves listen for?

    You don't. Your model should be doing validation on any attributes you try to update so your view needs to listen in case your setting of the attribute failed or the validation changed the value.

    What your view does is, it's tries to set a value on the model, the model then either sets it, changes the data and sets it, or rejects it. Your view needs to be updated accordingly.

    3) How can I push a new state based on a part of the model?

    // 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));
    
    0 讨论(0)
提交回复
热议问题