如何从车把模板访问骨干模型的计算字段?

时间:2012-05-18 08:07:05

标签: backbone.js handlebars.js

我想从模板访问我在模型(backbone.js)中实现的计算字段。 我是否需要始终定义帮助程序才能执行此操作?

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

4 个答案:

答案 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 });
        });
    },

Computed properties in Backbone

答案 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的通用版本。