是否有应对骨干非saveable值的标准方法。
如
MyModel = Backbone.extend(Backbone.Model, {
initialize: function () {
this.set({'inches': this.get('mm') / 25});
}
})
如果我调用保存()这个模型,因为是没有相应的数据库字段,将抛出一个错误inches
。 我能想到的一些方法来解决这个问题,但我想知道如果有一个久经考验的方法通常最适合用于本?
此刻我的首选解决方案是延长骨干toJSON
方法,并允许一个布尔参数的传递dontCleanup
允许它仍然会返回模型的所有值(包括非saveable的)时,它需要例如用于传递给一个模板。
我喜欢彼得·里昂的想法。 我已经想过了几次,但从来没有真正把它在的地方。 对于我已经处理了这个的所有方式,不过,这里有我的两个最爱:
非属性值
这一个很简单:不存储在模型中的标准属性需要的值。 相反,它直接连到对象:
myModel.someValue = "some value";
这里最大的问题是,你没有得到所有调用相关的事件的set
在模型上。 所以,我倾向于在这做了我的一切的方法来包装这件事。 举例来说,我穿上机型常用的方法是select
地说,这种模式已经被选择:
MyModel = Backbone.Model.extend({
select: function(){
if (!this.selected){
this.selected = true;
this.trigger("change:selected", this, this.selected);
}
}
});
在你的情况,我不知道这将是一个不错的办法。 你有数据,需要根据,在您的属性已经值来计算的。
对于这一点,我倾向于使用视图模型。
查看模型。
其基本思想是您创建一个骨干模式,即坚持-能,因为你通常会。 但是你一起去,并创建从原来的一个继承,并增加了所有你需要的数据另一种模式。
有一个非常大的数量的方式,你可以做到这一点。 以下是可能是一个非常简单的版本:
MyModel = Backbone.Model.Extend({ ... });
MyViewModel = function(model){
var viewModel = Object.create(model);
viewModel.toJSON = function(){
var json = model.toJSON();
json.inches = json.mm / 25;
return json;
};
return viewModel;
});
与此包裹的最大好处Object.create
是,你现在有一个原型继承的情况,因此,所有的从模型的标准功能还是很到位的。 我们刚刚在覆盖toJSON
在视图模型方法,使其返回与JSON对象inches
属性。
然后在需要这样的观点,你会在包装的初始化函数模型:
MyView = Backbone.View.extend({ initialize: function(){ this.model = MyViewModel(this.model); },
渲染:函数(){风险数据= this.model.toJSON(); //与返回inches
}});
你可以称之为new MyViewModel(this.model)
如果你想要的,但是这不会做任何事情一样,在最后,因为我们明确地从返回一个对象实例MyViewModel
功能。
当您的视图的渲染方法调用toJSON
,你会得到inches
与它的属性。
当然,也有一些潜在的内存问题和性能问题与此实现,但那些可以很容易地与视图模型的一些更好的代码来解决。 这种快速和肮脏的例子应该让你失望的道路,虽然。
我想,这应该这样做。 定义你的Model
defaults
为您有效的模式,然后只返回的子集this.attributes
期间是有效toJSON
。
var Model = Backbone.Model.extend({
defaults: {
foo: 42,
bar: "bar"
},
toJSON: function () {
var schemaKeys = _.keys(this.defaults);
var allowedAttributes = {};
_.each(this.attributes, function (value, key) {
if (_.include(schemaKeys, key)) {
allowedAttributes[key] = value;
}
return allowedAttributes;
}
});
需要注意的是_.pick
会使代码短一点,一旦你有下划线1.3.3可用。 我还没有看到过骨干的社区我的旅行是“久经考验”约定,自骨干留下这么多的选择余地,有时约定不出现,但我们会看看这个计算器问题的产量。
在Backbone.js的非持久化处理的属性已经做我的头了一段时间,特别是因为我一直在使用烬/烬数据,它通过计算性能,烬数据属性,或控制器处理各种情况下启动。
许多解决方案建议定制toJSON
方法。 然而,一些流行的骨干插件(特别是那些与嵌套模型处理),实现自己toJSON
方法,使一个呼叫Backbone.Model.prototype.toJSON
获得一个模型的属性的对象表示。 因此,通过覆盖toJSON
模型中定义的方法,你就会失去这些插件的一些(潜在的关键)功能。
我拿出最好是包括excludeFromJSON
模型定义按键的排列,并覆盖toJSON
的方法Backbone.Model.prototype
本身:
Backbone.Model.prototype.toJSON = function() {
var json = _.clone(this.attributes),
excludeFromJSON = this.excludeFromJSON;
if(excludeFromJSON) {
_.each(excludeFromJSON, function(key) {
delete json[key];
});
}
return json;
};
MyModel = Backbone.Model.extend({
excludeFromJSON: [
'inches'
]
});
通过这种方式,你只需要定义非持续键(如果你忘了这样做,你很快就会在您的服务器抛出一个错误提醒!)。 toJSON
将表现为正常的,如果没有excludeFromJSON
属性存在。
在你的情况, inches
是计算性能,源自mm
,所以是有意义的落实,这个是你的模型的方法(确保当毫米改变英寸的值是正确的):
MyModel = Backbone.Model.extend({
inches: function() {
return this.get('mm') / 25;
}
});
然而,这具有不同的方式访问到everyother属性下行。 理想情况下,你会希望保持它与访问其他属性保持一致。 这可以通过以下方式实现扩展默认get
方法 :
var getMixin = {
get: function(attr) {
if(typeof this[attr] == 'function') {
return this[attr]();
}
return Backbone.Model.prototype.get.call(this, attr);
}
};
MyModel = Backbone.Model.extend({
inches: function() {
return this.get('mm') / 25;
}
});
_.extend(MyModel.prototype, getMixin);
这将让你做的事:
new MyModel().get('inches');
这种方法不触及根本attributes
哈希,这意味着inches
不会出现在toJSON
表示, 除非你set
的值inches
后来,在这种情况下,你需要的东西像excludeFromJSON
阵列。
如果您有需要set
的inches
值,你可能还需要监听的变化和调整的价值mm
:
MyModel = Backbone.Model.extend({
initialize: function() {
this.on('change:inches', this.changeInches, this);
},
inches: function() {
return this.get('mm') / 25;
},
changeInches: function() {
this.set('mm', this.attributes.inches * 25);
}
});
_.extend(MyModel.prototype, getMixin);
请参阅上JSBin完整的例子 。
另外值得一提的是, 在的(官员?)目的toJSON
方法最近被重新定义为准备模型与服务器同步。 出于这个原因,调用toJSON
应该总是返回只有“持久化”(或“saveable”)的属性。