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