2

我有一个主干模型(我们称之为Foo),其中包含n个子模型(我们称之为它们Bar)的集合,在一个特定的视图中,我只想显示这些子模型中的m个,以及沿线的消息“ (nm)剩余”。

现在,我得到的是这样的:

var FooView = Backbone.View.extend({
    ...
    render: function() {
        this._barViews = [];
        var bars = this.model.get("bars");

        var that = this;
        _.each(bars.first(maxToShow), function(bar) {
            that._barViews.push(new BarView({model:bar}));
        }

        var remaining = bars.length - maxToShow;
        this.model.set("remaining", remaining > 0 ? remaining : undefined;

        var json = this.model.toJSON();
        $(this.el).html(this.template(json));

        _(this._holdViews).each(function(hv) {
            holdList.append($(hv.render().el));
        });
    }
});

这行得通,但感觉很hacky,因为我将“remainingMessage”注入到模型中,即使这是特定于这个特定视图的。(另一个视图可能显示所有的bars,或者一个都不显示,并且可能有也可能没有剩余的消息。)我对嵌套视图也不是很兴奋,因为它们意味着创建一个额外的模板文件并且必须记住包含它(FWIW,我使用 Handlebars.js 作为模板,带有服务器端编译)。

有没有更好的方法来 (1) 将bars集合过滤到maxShown项目,以及 (2) 生成/包含视图中剩余的数字?

4

1 回答 1

4

您需要一个“视图模型”——一个专门用于处理有关将使用它的特定视图的问题的模型。幸运的是,这在 JavaScript 中非常简单。

使用Object.create您可以获得一个新的对象实例,该实例继承自您作为参数传入的原始对象。这使我们能够用新代码“装饰”原始模型,而无需实际更改原始模型。

在您的情况下,我们想用剩余的信息装饰“foo”模型。不过,我们只需要toJSON结果中的该信息,因此我们只会将其添加到该方法中。



function buildFooViewModel(model){
  var foovm = Object.create(model);

  foovm.toJSON = function(){
    // call the original model's toJSON
    var args = Array.prototype.slice.apply(arguments);
    var json = model.toJSON.apply(this, args);

    // add the needed "remaining" data using your calculations, here
    json.remaining = bars.length - maxToShow;

    // send the json data back
    return json;
  }

}

var FooView = Backbone.View.extend({

  initialize: function(){
    // use the view model instead of the original
    this.model = buildFooViewModel(this.model);
  },

  render: function(){
    // your normal render stuff here... calling this.model.toJSON
    // will return your JSON data with the `remaining` field in it already
  }

});

我经常使用需要这样计算的视图来执行此操作。您可以在http://ravenhq.com上看到它,例如,在数据库管理屏幕中,显示已使用/剩余百分比以及类似的其他值。

于 2013-01-25T22:07:46.137 回答