I'm grappling with a web application that uses Marionette to render complex nested views. The challenge I face is minimizing reflows by ensuring child elements are rendered and placed in parent containers before being inserted into the DOM. How can I achieve this seamless rendering of child elements?
Currently, I render all children views in the onRender
function. While they seem to appear simultaneously with the parent view, there's no clear confirmation if this is the intended approach. I've also explored using onBeforeShow
, which triggers before insertion into the DOM, but it complicates rerendering as straightforwardly calling render
becomes impossible.
To provide more context, here's a snippet of code illustrating my predicament:
var Layout = LayoutView.extend({
//...
initialize: function() {
listenTo(this.model, "some event indicating data change", this.render);
},
onRender: function() {
//Will the new view render in time to reduce page reflows effectively?
this.someRegion.show(new view(new model()));
}
});
Alternatively, employing onBeforeShow
allows passing a reference to the container region
var Layout = LayoutView.extend({
//...
initialize: function() {
listenTo(this.model, "some event indicating data change", this.callback);
},
callback: function() {
this.container.show(this, {forceShow: true});
},
onBeforeShow: function() {
//While preventing page reflows, this method isn't ideal.
this.someRegion.show(new View(new Model()));
}
});
var LayoutContainer = LayoutView.extend({
//...
onRender: function() {
var model = new LayoutModel();
var layout = new Layout({
model: model,
container: this.containerRegion
});
this.containerRegion.show(layout);
}
});
Another option involves a parent object overseeing when to instruct the view to render
var Layout = LayoutView.extend({
//...
onBeforeShow: function() {
//While preventing page reflows, this method isn't ideal.
this.someRegion.show(new View(new Model()));
}
});
var LayoutContainer = LayoutView.extend({
//...
onRender: function() {
var model = new LayoutModel();
this.layout = new Layout({ model: model });
listenTo(model, "some event indicating data change", this.rerenderSubview);
this.containerRegion.show(this.layout);
},
rerenderSubview: function() {
this.containerRegion.show(this.layout, {forceShow: true});
}
});