我有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();
};
答案 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);
}
}
});