我想要一个带有float属性的Backbone模型,但不要过多担心变量类型。
我想在模型中封装值解析,所以我想覆盖set
函数:
var Place = Backbone.Model.extend({
set: function(attributes, options) {
if (!_.isEmpty(attributes.latitude)){
attributes.latitude == parseFloat(attributes.latitude);
}
if (!_.isEmpty(attributes.longitude)){
attributes.longitude == parseFloat(attributes.longitude);
}
Backbone.Model.prototype.set.call(this, attributes, options);
}
});
然而,这似乎很麻烦,因为我在验证方法中会有类似的逻辑,并且可能在多个模型中重复。我不认为View应该处理这些转换。
那么最好的方法是什么?
答案 0 :(得分:2)
为您的模型使用验证插件,以便您可以以通用方式验证输入。
有几个,包括我写的一个:
然后您不必担心在其他地方执行数据验证 - 您的模型会执行此操作并发送出您可以收听的error
消息并提供适当的反馈。
此外,在极少数情况下,lat / lng对可以是整数,例如Greenwich England:0,0或北极:90,180。由于JavaScript只有“number”,因此parseFloat的任何有效输入对parseInt也有效。
但是parseFloat将始终返回一个浮点数。
答案 1 :(得分:0)
我的解决方案是用预处理器代理替换Backbone.Model.prototype.set
:
/**
* Intercept calls to Backbone.Model.set and preprocess attribute values.
*
* If the model has a <code>preprocess</code> property, that property will be
* used for mapping attribute names to preprocessor functions. This is useful
* for automatically converting strings to numbers, for instance.
*
* @param Backbone
* the global Backbone object.
*/
(function(Backbone) {
var originalSet = Backbone.Model.prototype.set;
_.extend(Backbone.Model.prototype, {
set: function(key, val, options) {
if(!this.preprocess) {
return originalSet.apply(this, arguments);
}
// If-else copied from Backbone source
if (typeof key === 'object') {
attrs = key;
options = val;
} else {
(attrs = {})[key] = val;
}
for(attr in this.preprocess) {
if(_.has(attrs, attr)) {
attrs[attr] = this.preprocess[attr](attrs[attr]);
}
}
return originalSet.call(this, attrs, options);
},
});
})(Backbone);
在此之后,具有preprocess
属性的模型将使用它将属性名称映射到预处理器函数。例如,preprocess: { age: parseInt }
表示每当设置age
属性时,该值将在实际设置之前通过parseInt
传递。没有相应preprocess
条目的属性不会受到影响。
使用示例:
var Thing = Backbone.Model.extend({
preprocess: {
mass: parseInt,
created: function(s) { return new Date(s); },
},
});
var t = new Thing({
label: '42',
mass: '42',
created: '1971-02-03T12:13:14+02:00',
});
console.log(t.get('label')+3); // 423
console.log(t.get('mass')+3); // 45
console.log(t.get('created').toLocaleString('ja-JP', { weekday: 'short' })); // 水
{ validate: true }
set
validate
中复制预处理,因为这是在调用validate
之前发生的(这也可能是下面的内容)validate
之前发生,因此可能会中断验证。 JavaScript解析方法通常返回无效值而不是抛出异常(即parseInt('foo')
返回NaN
),因此您应该能够检测到它。