11

質問:特定の方法で保存する必要がある属性がある場合、backbone.js モデルを初期化する適切な方法は何ですか? 特別なフォーマットを必要としない属性をマップする必要がありますか? backbone.js はある種の自動マッピングを行っていると思いました。

例:

var MyModel = Backbone.Model.extend({

    initialize: function (options) {

        // These attributes need to be stored in a different format
        // Dates
        this.startYear = new Date(options.startTime).getFullYear();
        // Rounding numbers
        this.wholeNumber = Math.Round(options.numberWithDecimals);
        // Storing empty strings as nulls
        if (options.fullName == null || options.fullName == "") {
            this.fullName == null;
        } else {
            this.fullName = options.fullName;
        }

        // These are fine as they are
        this.fieldA = options.fieldA;
        this.fieldB = options.fieldB;
        this.fieldC = options.fieldC;
    },
});
4

3 に答える 3

13

First you have to differentiate between attributes and instance variables.

Attributes: IMHO, it should be plain objects as String or Integer. They travel around the client and the server through the REST API. They are manipulated through the Model.get()/Model.set() methods. They are sent to the server through the Model.toJSON() (also they use to be sent to the template using the same .toJSON() method. If they change in some way then Backbone events are triggered. You can customize the initialization of this attributes manipulating the server side JSON information before it is sent to the Model overriding the Model.parse() method as @muistooshort has suggested.

Instance Variables: (the this.myAttribute thing) They can be complex objects. The don't trigger any implicit event in their change and they are not sent to the server in the save and update calls, and, in an standard way, they are not sent to the template.

In your example you're not storing any complex object and if you are not affraid that your model is gonna send more attributes to the server than it receives from the server you can go for the @muistooshort suggestion:

// code no tested
var MyModel = Backbone.Model.extend({
  parse: function(resp, xhr) {
    resp.startYear = new Date( resp.startTime ).getFullYear();
    resp.wholeNumber = Math.Round( resp.numberWithDecimals );
    if( resp.fullName == "" ) resp.fullName == null;

    return resp;
  },
});

Just remember you these are attributes and you have to access them in this way my_model.get( "startYear" )

The only problem with this solution is the derived attributes won't be updated if the original attribute changes. So you can come with another implementation:

// code no tested
var MyModel = Backbone.Model.extend({
  initialize: function(){
    this.updateAttributes();
    this.on( "change", this.updateAttributes, this );
  },

  updateAttributes: function() {
    this.set( "startYear", new Date( this.get( "startTime" ) ).getFullYear() );
    this.set( "wholeNumber", Math.Round( this.get( "numberWithDecimals" ) ) );
    if( this.get( "fullName" ) == "" ) this.set( "fullName", null );
  },
});

Updated

As @TomTu has suggested if your onlive attributes are only needed to feed the templates then a decorator is the best solution: https://stackoverflow.com/a/9687672/316700

于 2012-09-05T20:15:38.667 に答える
0

すでに回答されていますが、もう少しきちんとするために:

var contact = Backbone.Model.extend({
       parse: function (response) { 
           response.newAttribute = response.alreadyProvidedAttribute; 
           return response;
      }
 });
于 2014-11-18T14:50:28.437 に答える