2011-11-23 35 views
0

我建立一个小Backbone.js的应用并增加了一些自定义的干将的车型之一(该名称的getter返回例如串联一线和姓):呈现视图与覆盖干将骨干

PersonModel = Backbone.Model.extend({ 
    get: function (attr) { 
    if (typeof this[attr] == 'function') { 
     return this[attr](); 
    } 
    return Backbone.Model.prototype.get.call(this, attr); 
    }, 

    name: function() { 
    return firstName + " " + lastName; 
    } 
}) 

我现在可以使用person.get("name")来检索名称,很好。但是,当我在模型上调用toJSON时,这些值不包含在内(我想这是有道理的)。问题是我用它来渲染我的意见:

this.template({people: this.collection.toJSON()}); 

在Backbone.js中做到这一点的最佳方法是什么?用覆盖的getter手动创建JSON?

谢谢!

+0

为什么不让“名称”成为一个真正的属性? –

+0

因为我不想要一个静态属性。如果我在这个例子中改变'firstName','name'应该返回更新的名字,我不想单独改变它们。那有意义吗? – Cimm

回答

5

你可以在PersonModel提供自己的toJSON方法:

toJSON: function() { 
    var attr = Backbone.Model.prototype.toJSON.call(this); 
    attr.name = this.name(); 
    return attr; 
} 

collection toJSON只是调用toJSON每个型号:

// The JSON representation of a Collection is an array of the 
// models' attributes. 
toJSON : function() { 
    return this.map(function(model){ return model.toJSON(); }); 
}, 

因此增加自己toJSON到您的模型应该工作。

您还可以添加name作为一个真正的属性,然后调整模型的validate方法来更新name如果firstNamelastName变化和忽略任何直接试图改变name或抱怨“试图修改只读属性“当有人试图通过name更改为set。没有什么说validate不能更改它给出的属性对象,因此您可以在validate返回之前给{firstName: 'x'}并将其更改为{firstName: 'x', name: 'x ' + this.get('lastName')}。这可能是validate的滥用,但是没有明确禁止validate更改属性集,它是唯一的钩子。我想你可以让模型听自己的firstNamelastName来更改事件,然后触发set({name: ...}),但如果其他人只注意名字和姓氏,则可能会遇到事件排序问题。

+0

+1给予所有选项,但我不会使用验证来实现这个看起来很丑陋的解决方案:P虽然我喜欢第一个解决方案,但是今天我用一个稍微不同的方法回答了一个类似的帖子,用toJSON()在一个toFullJSON()方法中调用,愚蠢的我,我可以重写默认值,只是添加了额外的属性:) – Sander

+0

@Sander:我同意'validate'部分不是很好,但没有任何支持对于Backbone中的虚拟属性,自己设置钩子的方式并不多;构造函数/解析/验证是关于如果你需要做一些非标准的事情。我会说,这是一个与通常的“一个对象是一个结构”方法有关的问题的例子,有很多ORM-ish系统。 –

+0

谢谢,这完全按照你的解释工作。 – Cimm

0

我选择扩展骨干模型,并让我所有的应用程序模型都从Base模型扩展而来,其中包括一个方法,以便启用设置虚拟属性,这些方法合并到模型toJSON方法中。

toJSON: function() { 
    return _.extend(toJSON.__super__.constructor.apply(this, arguments), this.getVirtualAttributes()); 
    }, 
    getVirtualAttributes: function() { 
    var attrs, key; 
    attrs = {}; 
    for (key in this.virtualAttributes) { 
     attrs[key] = this.virtualAttributes[key].call(this); 
    } 
    return attrs; 
    } 

这使您可以在可用于检索虚拟/动态属性的模型上定义virtualAttributes对象。

virtualAttributes: { 
    email_length: function() { 
    return this.get("email").length 
    } 
}