Backbone中的计算属性

17

我有一个场景,即客户端操作的数据以不同于服务器表示和交互的方式呈现和交互。

考虑从服务器返回的以下event资源。

{
  "id": 123,
  "start_at": 1331336004906,
  "end_at": 1331337704906
}

以下是编辑用的模板:

<form>
  <!-- Notice how date and time are separated in the interface -->
  <input type="text" name="start_date" value="{{start_date}}" />
  <input type="text" name="start_time" value="{{start_time}}" />

  <!-- Instead of asking for an end date/time, we ask for the duration -->
  <input type="text" name="duration" value="{{duration}}" />

  <input type="submit" />
</form>

如果我想把start_datestart_timeduration作为我的Backbone模型的属性,但不想将它们发送到服务器,我应该怎么办? 我需要修改.toJSON()吗?


事件资源格式有什么问题,它们不是时间戳吗? - mpm
参见:https://dev59.com/cmgv5IYBdhLWcg3wXPsu - Curtis Yallop
4个回答

23

我正在使用initialize()函数和change事件监听器的组合来更新派生属性。其思想是首先在模型初始化时计算属性,其次让模型监听自身的更改并相应地更新属性。

我的解决方案大致如下:

MyModel: Backbone.Model.extend({
    initialize: function() {
        this.updateDerivedAttributes();
        this.on('change:start_at', this.updateDerivedAttributes, this);
    },
    updateDerivedAttributes: function() {
        this.set({
            start_date: Utils.dateFromDate( this.get( "start_at" ) ),
            start_time: Utils.timeFromDate( this.get( "start_at" ) ),
            duration: Utils.youGetTheIdea()
        }, {silent:true});
    }
});

5

我们非常习惯于发送model.toJSON()填充模板。而且这种方法很棘手,因为其他组件也在使用它。

但是,我们可以通过自定义model.toJSONDecorated()方法来填充模板,代码可能如下所示:

# in your Backbone.Model
toJSONDecorated: function(){
  return 
    _.extend( 
      this.toJSON(), 
      {
        start_date : Utils.dateFromDate( this.get( "start_at" ) ),
        start_time : Utils.timeFromDate( this.get( "start_at" ) ),
        duration   : Utils.youGetTheIdea( :) )
      } 
    );
}

当然,这破坏了一些模式,但我可以接受。如果你不能接受,你可以将这个逻辑移到一个 Decorator 类中,正如其他答案中所建议的那样。


5
你有些选项:
  • 覆盖toJSON以返回计算出的duration

  • 在BackboneModel上创建一个duration()方法。唯一的缺点是你需要用不同的方式调用它(obj.duration()代替obj.get('duration'))。在你的视图中,将obj.toJSON()传递给你的模板,并混入duration属性。

  • 使用https://github.com/asciidisco/Backbone.Mutators(或类似的工具)来创建一个派生的getter,用于获得duration


谢谢。我通常采用最佳描述的方法,但我不知道Mutators:它看起来非常有用和做得很好。 - Giovanni Filardo

4

你的模型应尽可能与服务器端一致,因此请使用 start_atend_at。这将大大简化您的 sync() 操作。

在编辑表单的 视图 上,您可以:

  1. 通过简单的函数计算 start_datestart_timeduration 并在模板中调用它们。
  2. 在提交时转换为 start_atend_at

1
把这个放在视图里面不会导致很多冗余代码吗?我将在整个网站上使用相同的虚拟属性,其中一个事件有多个视图来展示它。 - bloudermilk
制作一个基础视图并进行扩展。 - ggozad
1
好的,不错的想法!我也认为装饰器模式可以解决这个问题。 - bloudermilk
当然,如果复杂性需要超出伪继承的范畴,装饰器似乎是一个绝佳的选择! - ggozad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接