Backbone.js - 正确的模型初始化

JT7*_*703 10 backbone.js

问题:当存在需要以特定方式存储的属性时,初始化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;
    },
});
Run Code Online (Sandbox Code Playgroud)

fgu*_*len 12

首先,你必须区分attributesinstance variables.

属性:恕我直言,它应该是普通对象,如String或Integer.他们通过REST API在客户端和服务器周围旅行.它们通过Model.get()/Model.set()方法进行操作.它们通过Model.toJSON()发送到服务器(它们也用于template使用相同的.toJSON()方法发送.如果它们以某种方式改变,则会触发Backbone事件.您可以自定义此attributes操作服务器端的初始化JSON信息在被发送到模型之前覆盖Model.parse()方法,如@muistooshort所建议的那样.

实例变量 :( this.myAttribute东西)它们可以是复杂的对象.不会在更改中触发任何隐式事件,并且它们不会在saveupdate调用中发送到服务器,并且以标准方式,它们不会发送到模板.

在你的例子中,你没有存储任何复杂的对象,如果你不担心你的模型会向服务器发送比从服务器收到的更多属性,你可以去找@muistooshort建议:

// 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;
  },
});
Run Code Online (Sandbox Code Playgroud)

只记得你这些是属性 ,你必须以这种方式访问​​它们my_model.get( "startYear" )

此解决方案的唯一问题是,如果原始属性更改,则不会更新派生属性.所以你可以带来另一个实现:

// 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 );
  },
});
Run Code Online (Sandbox Code Playgroud)

更新

正如@TomTu所建议的那样,如果仅需要提供onlive属性来提供模板,那么装饰器是最佳解决方案:https://stackoverflow.com/a/9687672/316700

  • AFAIK你必须说'new M({...},{parse:true})`以使构造函数使用`parse`,这似乎没有在任何地方记录. (3认同)