Computed properties in Backbone

北慕城南 提交于 2019-11-26 16:28:46

问题


I have a scenario where the data being manipulated on the client is presented and interacted with in a different way than it is represented on the server.

Consider the following event resource returned from the server.

{
  "id": 123,
  "start_at": 1331336004906,
  "end_at": 1331337704906
}

And the following template for editing:

<form>
  <!-- Notice how date and time are separated in the interface -->
  <input type="text" name="start_date" value="{{start_date}}" />
  <input type="text" name="start_time" value="{{start_time}}" />

  <!-- Instead of asking for an end date/time, we ask for the duration -->
  <input type="text" name="duration" value="{{duration}}" />

  <input type="submit" />
</form>

How would I go about treating start_date, start_time, and duration as attributes in my Backbone model without sending them to the server? Am I supposed to modify .toJSON()?


回答1:


Your model should correspond as closely as possible to what you have server side. So stick with start_at and end_at. That will greatly simplify your sync() operations.

On your edit form's View, you can:

  1. Compute start_date, start_time, duration through simple functions and call them in the template.
  2. Convert to start_at and end_at on submitting.



回答2:


I am using a combination of the initialize() function together with change event listeners to update derived attributes. The idea is first to compute the attributes on model initialization, and second to let the model listen to its own changes and update the attributes accordingly.

My solution looks roughly like this:

MyModel: Backbone.Model.extend({
    initialize: function() {
        this.updateDerivedAttributes();
        this.on('change:start_at', this.updateDerivedAttributes, this);
    },
    updateDerivedAttributes: function() {
        this.set({
            start_date: Utils.dateFromDate( this.get( "start_at" ) ),
            start_time: Utils.timeFromDate( this.get( "start_at" ) ),
            duration: Utils.youGetTheIdea()
        }, {silent:true});
    }
});



回答3:


We are very used to send model.toJSON() to feed the template. And this method is very tricky to overwrite because is used by other components.

But we can feed the template with a custom model.toJSONDecorated() method that can look like this:

# in your Backbone.Model
toJSONDecorated: function(){
  return 
    _.extend( 
      this.toJSON(), 
      {
        start_date : Utils.dateFromDate( this.get( "start_at" ) ),
        start_time : Utils.timeFromDate( this.get( "start_at" ) ),
        duration   : Utils.youGetTheIdea( :) )
      } 
    );
}

Of course this is breaking a few patterns, I can live with it, if you don't you can move this logic to a Decorator class as people have suggested in other answers.




回答4:


You have some options:

  • Override toJSON to return the computed duration

  • Create a duration() method on the Backbone Model. Only downside that you have to call it differently (obj.duration() instead of obj.get('duration')). In your view that hands obj.toJSON() to your template, mix in the duration attribute

  • Use https://github.com/asciidisco/Backbone.Mutators (or similar) to create a derived getter for duration



来源:https://stackoverflow.com/questions/9642439/computed-properties-in-backbone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!