如何从车把模板访问主干模型的计算字段?
Posted
技术标签:
【中文标题】如何从车把模板访问主干模型的计算字段?【英文标题】:How to access a calculated field of a backbone model from handlebars template? 【发布时间】:2012-05-25 19:30:57 【问题描述】:我想从模板访问我在模型 (backbone.js) 中实现的计算字段。 我是否需要始终定义一个助手来执行此操作?
我认为问题与我将模型传递给模板的方式有关。 如果我通过 this.model.toJSON() 我可以访问属性,但不能访问我在其中定义的函数。 如果我直接传递 this.model,我可以访问该函数,但不能访问主干模型的属性。
【问题讨论】:
我认为问题与我将模型传递给模板的方式有关。 【参考方案1】:始终将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;
)
现在您可以从toJSON
返回的JSON 中访问myValue
,这意味着您可以在视图中访问它。
正如您所提到的,另一个选项是构建辅助方法并将它们注册到 Handlebars。除非您的某些功能会根据模板的呈现方式和/或传递给模板的数据而发生变化,否则我不会为此烦恼。
【讨论】:
重写toJSON
有一个缺点:Backbone.sync
使用 toJSON
序列化模型(更准确地说,sync
调用 JSON.stringify
调用 toJSON
)所以现在服务器将请参阅myValue
,即使它可能并不关心它。这可能是也可能不是问题。【参考方案2】:
这是另一种可能性:(来自模型初始化)
initialize: function()
this.on("change", function ()
this.set( calculatedColumn: this.get("otherColumn") , silent: true );
);
,
Computed properties in Backbone
【讨论】:
【参考方案3】:我也遇到过同样的问题。 @DerickBailey 是对的,当然,覆盖 toJSON 可以完成这项工作。但它也会泄露到与服务器的通信中(请参阅 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
);
如果您是 Marionette 用户,那么此时您已经完成了。 foo
显示在您的模板中,就好像它是模型属性一样。
在普通的 Backbone 视图中,只需在渲染时调用 myModel.export()
或 myCollection.export()
而不是它们的 toJSON 对应项。
对于接受参数的方法,有一个onExport
处理程序。同样,示例位于docs。
【讨论】:
【参考方案4】:最好的方法是将其添加到您的模型中:
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,它可以应用于任何模型。
【讨论】:
以上是关于如何从车把模板访问主干模型的计算字段?的主要内容,如果未能解决你的问题,请参考以下文章