我想从模板访问我在模型(backbone.js)中实现的计算字段。 我是否需要始终定义帮助程序才能执行此操作?
我认为问题与我将模型传递给模板的方式有关。 如果我传递this.model.toJSON(),我可以访问属性,但不能访问我在其中定义的函数。 如果我直接传递this.model,我可以访问该函数,但不能访问骨干模型的属性。
答案 0 :(得分:17)
始终将this.model.toJSON()
传递给您的模板。
获取计算值所需的操作是覆盖模型上的toJSON
方法。
MyModel = Backbone.Model.extend({
myValue: function(){
return "this is a calculated value";
},
toJSON: function(){
// get the standard json for the object
var json = Backbone.Model.prototype.toJSON.apply(this, arguments);
// get the calculated value
json.myValue = this.myValue();
// send it all back
return json;
}
})
现在您可以从myValue
返回的JSON访问toJSON
,这意味着您可以在视图中访问它。
正如您所提到的,另一个选项是构建帮助器方法并使用Handlebars注册它们。除非你有一些功能根据模板的呈现方式而变化,和/或传递给模板的数据,否则我不会为此烦恼。
答案 1 :(得分:4)
这是另一种可能性:(从模型初始化)
initialize: function() {
this.on("change", function () {
this.set({ calculatedColumn: this.get("otherColumn") }, { silent: true });
});
},
答案 2 :(得分:0)
我遇到了同样的问题。当然,@ DerickBailey是正确的,它可以胜任JSON。但它也泄漏到与服务器的通信中(参见muu对他的回答的评论)。
所以最终,我已经构建了一个Backbone插件来专门处理数据导出到模板,并且只需要少量工作:Backbone.Marionette.Export。它还处理嵌套结构,处理循环引用等。请参阅docs。
这是它的工作原理。将插件文件包含在项目中并声明
MyModel = Backbone.Model.extend({
foo: function () {
return "I am a calculated value";
},
exportable: "foo" // <-- this is the one line you have to add
});
如果您是木偶用户,此时您已经完成了。 foo
在模板中显示为模型属性。
在简单的Backbone视图中,在渲染时只需调用myModel.export()
或myCollection.export()
而不是toJSON对应物。
对于接受参数的方法,有一个onExport
处理程序。示例再次出现在docs。
答案 3 :(得分:-1)
最好的方法是将其添加到您的模型中:
function initialize() {
this.set("calculatedColumn", function () { return this.otherColumn; });
}
主干模型通常在“model.attributes”内部存储实际数据值。这就是为什么当您将模型直接传递给模板时,它只将函数直接添加到模型而不是任何数据。如果你使用model.toJSON(),它通常在主干中实现为_.clone(model.attributes)(参见backbone.js)。因此,您拥有数据而不是直接添加到模型中的函数。这就是为什么上面的工作 - 你在model.attributes上设置函数,而不是在模型对象本身。不要直接引用model.attributes,使用model.get(“calculatedColumn”)和model.set(“calculatedColumn”,...)。
因此model.get(“calculatedColumn”)返回一个函数。如果你在把手中去{{calculatedColumn}}(假设你正在使用把手),它会显示该函数返回的值。但是,CalculationColumn将不会被发送到服务器,因为backbone会对同步的model.toJSON执行JSON.stringify(在backbone.js中),而JSON.stringify会忽略函数。如果您希望JSON.stringify不忽略该函数(因此只要在模型上运行toJSON时,函数就会转换为数据值 - 在视图渲染和模型同步期间),就像@Derick Bailey描述的那样覆盖model.toJSON。
此外,您可以从Backbone.Model派生自己的BaseModel并覆盖.toJSON,并在需要时从BaseModel派生所有模型。那么你需要一个可以应用于任何模型的.toJSON的通用版本。