如何在CollectionView中呈现与DOM相关的视图?

时间:2012-06-04 19:22:08

标签: backbone.js marionette

我有Marionette.CollectionView,其中会显示ItemView个列表。在render()期间,我使用ItemView的model使用Raphael绘制一些SVG。

拉斐尔要求我为其画布指定高度和宽度,我通常会从this.$el获取。但是,$el(作为空<div>)在添加到DOM并且CSS规则应用于它之前没有维度,所以我需要延迟渲染,直到我知道视图在DOM中。

问题是Marionette.CollectionView在呈现之前不会向DOM添加子视图。如何在不重新实现CollectionView的一半的情况下覆盖此行为?

示例代码

// Renders a single object.
var ItemView = Marionette.ItemView.extend({
    template: "#item-view-template",
    onRender: function() {
        var svgEl = this.$el.find("div.svg-canvas");
        // Raphael needs the element's width and height, which
        // is 0 until this.$el is in the DOM.
        var paper = Raphael(svgEl.get(0), svgEl.height(), svgEl.width());
        // ... draw some SVG...
    }
});

// Renders a collection of objects.
var ListView = Marionette.CollectionView.extend({
    itemView: ItemView,
    model: MyModel
});

// Main point of entry.
MyApp.show = function() {
    var collection = new MyCollection();
    var listView = new ListView({ collection: collection });
    MyApp.mainRegion.show(listView);
    collection.fetch();
};

1 个答案:

答案 0 :(得分:10)

onRender将无法满足您的需求,因为在渲染视图时会调用此方法 - 但不保证视图已添加到DOM中。

为此,您需要一个onShow方法,当您在区域中显示视图时,该方法将由区域调用。问题是当前实现仅在您直接传入的视图上调用onShow - 在这种情况下是集合视图。因此,您需要以一种方式实现onShow,使其在所有集合视图的子节点上调用该方法。


Marionette.CollectionView.extend({
  // ...  

  onShow: function(){
    _.each(this.children, function(childView){
      if (childView.onShow){ childView.onShow(); }
    });
  }
});

应该这样做。当你致电MyApp.mainRegion.show(listView)时,它会调用集合视图的onShow方法,然后在子节点上调用它(如果它在那里)。


在注释中的讨论中,即使在调用父视图的onShow并且将一个项添加到子视图之后,也会调用将保证子视图的onShow方法的实现。以后收集:


ItemView = Marionette.ItemView.extend({
  // ...

  onShow: function(){
    // I am guaranteed to be called from the CollectionView
    // because the CollectionView registers me in a promise
  }
});

CollectionView = Marionette.CollectionView.extend({

  initialize: function(){
    this.onShowCallbacks = new Marionette.Callbacks();
  },

  onShow: function(){
    this.onShowCallbacks.run();
  },

  appendHtml: function(cv, iv){
    cv.append(iv.el);

    // promise to run 'onShow' if it exists
    if (iv.hasOwnProperty("onShow")){
      this.onShowCallbacks.add(iv.onShow);
    }
  }
});

此优惠还有:https://gist.github.com/2872526