如何从 Marionette.js ItemView 模板访问 Backbone.Model 方法?

Posted

技术标签:

【中文标题】如何从 Marionette.js ItemView 模板访问 Backbone.Model 方法?【英文标题】:How to access Backbone.Model methods from Marionette.js ItemView template? 【发布时间】:2014-02-01 07:35:36 【问题描述】:

我正在尝试使用主干/marionette.js 从 .eco 模板中访问模型的方法。我有一个带有day() 方法的Expense 模型,该方法使用moment.js 返回'13th';例如:

class Expense extends Backbone.Model
  day: ->
    moment.get('date').format('Do')

我可以如下新建Expense,并调用day()方法:

coffee = new Expense(name: "Coffee", amount: 2.50, date: "2014-01-13T13:50:00Z")
coffee.day() # 13th

但是,尝试从以下视图和模板中访问 day() 会给我带来一些问题:

class ExpenseView extends Marionette.ItemView
  template: "views/_expense"
# views/_expense.jst.eco
<h3 class="expense__name"><%= @name %></h3>
<p class="expense__day"><%= @day() %></p>

理解为什么它不起作用...ItemView 调用 serializeData 返回 @model.toJSON()...因此,Expenseday() 方法是'不可访问。骨干/牵线木偶社区中是否存在使模型方法可用于模板的既定模式?

到目前为止,我已经完成了以下工作:

class ExpenseView extends Marionette.ItemView
  template: "views/_expense"

  serializeData: ->
    _.extend(@model.toJSON(), model: @model)

  templateHelpers:
    day: ->
      @model.day()

但我不确定这是否是解决问题的最佳方法?谢谢!

【问题讨论】:

【参考方案1】:

您始终可以将其添加到 templateHelpersserializeData - 但您真正要问的是一个虚拟属性 - 可以成为每个模板的一部分,一个仅用作 @ 一部分的属性987654325@。通过这种方式,我们还可以在sync 事件(例如save())上禁用它与服务器同步

有几个插件可以做到这一点,我个人最喜欢使用的是Backbone Mutators - https://github.com/asciidisco/Backbone.Mutators

Backbone Computed Fields - https://github.com/alexanderbeletsky/backbone-computedfields 这样的其他人会为您提供类似 Ember 的计算属性。

使用 Backbone Mutators,您可以在 Backbone 模型中编写您的 mutators。

class Model extends Backbone.Model
  mutators:
    day: ->
      moment.get('date').format('Do')

或者防止'day'属性同步到后端...

class Model extends Backbone.Model
  mutators:
    day:
      get: -> moment.get('date').format('Do')
      transient: true

day 属性现在将出现在所有 toJSON() 调用中。

【讨论】:

感谢 Brian,我非常喜欢这个 Backbone.Mutators 插件!我喜欢它如何将逻辑从我的视图中移到模型中——有点像 Rails 中的 :scope。 transient: true 也是一个不错的补充!【参考方案2】:

你为什么不把它添加到 serializeData ? (不记得 Coffee 语法了……)

serializeData: function()
    var data = _.clone(this.model.attributes);
    data.day = this.model.day();
    return data;

【讨论】:

谢谢大卫,我在想也许重写ExpensetoJSON 方法会更好...这样逻辑被封装在模型而不是视图中? 问题是如果你将它添加到toJSON 它也会被发送到 API 端点,这可能是一个问题。 啊,我明白了。也许我可以在所有Marionette.Views 中扩展serializeData,这样它就会调用一个新方法toData(或更好的名称),如果它存在的话,否则就照常调用toJSON。然后我可以选择在我的任何模型中实现toData 以将模型属性与我选择的任何自定义属性合并? 这是可能的。或者使用您要添加的额外参数定义一个 extendJSON 方法。然后在 Marionette 的serailzeData 中,您只需将_.extend 添加extendJSON 的结果返回的正常值(如果定义了extendJSON)。这样可以避免代码重复。

以上是关于如何从 Marionette.js ItemView 模板访问 Backbone.Model 方法?的主要内容,如果未能解决你的问题,请参考以下文章

Marionette.js 与 Chaplin.js 的比较

如何进行backbone.js UI测试

如何创建一个用户受损的可访问网站:不用鼠标上网?

如何从其他面板从 JTextField 获取输入

如何从外部从 GitHub 加载 JavaScript 文件? [复制]

如何将数据从回收器适配器发送到片段 |如何从 recyclerview 适配器调用片段函数