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

首先,您必须区分attributesinstance variables

属性:恕我直言,它应该是字符串或整数形式的普通对象。它们通过 REST API 在客户端和服务器之间移动。它们通过Model.get() / Model.set()方法进行操作。它们通过Model.toJSON()发送到服务器(也使用template相同的.toJSON()方法发送到服务器。如果它们以某种方式发生变化,则触发Backbone 事件。您可以自定义此attributes操作服务器端的初始化正如@muistooshort 所建议的,在将JSON 信息发送到覆盖Model.parse()方法的模型之前。

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

在您的示例中,您没有存储任何复杂的对象,并且如果您不害怕您的模型将向服务器发送的属性多于从服务器接收的属性,您可以寻求@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;
  },
});

请记住,这些是属性 ,您必须以这种方式访问​​它们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 );
  },
});

更新

正如@TomTu 所建议的,如果您的在线属性只需要提供模板,那么装饰器是最好的解决方案:https ://stackoverflow.com/a/9687672/316700

于 2012-09-05T20:15:38.667 回答
2

如果您只需要在模板中使用的辅助值,您可以在覆盖的toJSON方法中计算它们,该方法将添加您在视图中表示模型时可能需要的所有额外属性。

正如 Backbone.js 的文档所说

模型.toJSON()

返回模型属性的副本以进行 JSON 字符串化。这可用于持久化、序列化或 在移交给视图之前进行扩充。...

正如我在另一个答案的评论中提到的那样 - 更改parse方法中的模型将导致创建开销,每次保存模型时都会将其发送到服务器,应该被认为是一种草率和不好的做法

由于模型初始化不会以与视图类似的方式将选项绑定到模型实例,因此您始终可以在初始化方法中执行此操作,然后根据您的要求从覆盖的 toJSON 方法中引用选项想要达到

于 2012-09-06T14:48:28.073 回答
0

已经得到回答,但只是为了更整洁一点:

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