13

我想从模板访问我在模型(backbone.js)中实现的计算字段。我是否总是需要定义一个助手来做到这一点?

我认为问题与我将模型传递给模板的方式有关。如果我通过 this.model.toJSON() 我可以访问属性,但不能访问我在其中定义的函数。如果我直接传递 this.model,我可以访问该函数,但不能访问主干模型的属性。

4

4 回答 4

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。除非您有一些功能会根据模板的呈现方式和/或传递给模板的数据而发生变化,否则我不会为此烦恼。

于 2012-05-18T13:22:48.957 回答
4

这是另一种可能性:(来自模型初始化)

initialize: function() {
        this.on("change", function () {
            this.set({ calculatedColumn: this.get("otherColumn") }, { silent: true });
        });
    },

Backbone 中的计算属性

于 2014-07-17T22:33:29.937 回答
0

我有同样的问题。@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中。

于 2013-11-21T15:54:17.030 回答
-1

最好的方法是将其添加到您的模型中:

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 可以应用于任何模型。

于 2014-07-17T22:15:11.440 回答