我有一个使用 Marionette 的 Web 应用程序,它经常需要渲染大型嵌套 View 树。我想通过确保在父容器放置在 DOM 中之前渲染子元素并将其放置在父容器中来避免尽可能多的回流。我如何渲染这些子元素来实现这一点?
我目前正在 onRender
函数中渲染所有 subview ,据我所知,它们与父 View 同时出现,但我找不到任何文档这告诉我这就是它的预期用途。我还考虑过 onBeforeShow
的使用,我知道它肯定是在将 View 放入 DOM 之前调用的,但它使重新呈现变得更加复杂,因为我不能只调用 然后渲染
。
根据要求,这里有一些代码可以更好地了解我的情况:
var Layout = LayoutView.extend({
//...
initialize: function() {
listenTo(this.model, "some event indicating that data changed", this.render);
},
onRender: function() {
//Will this new view render at the appropriate time to minimize page reflows?
this.someRegion.show(new view(new model()));
}
});
如果我选择使用 onBeforeShow
,那么我可以传递对容器区域的引用
var Layout = LayoutView.extend({
//...
initialize: function() {
listenTo(this.model, "some event indicating that data changed", this.callback);
},
callback: function() {
this.container.show(this, {forceShow: true});
},
onBeforeShow: function() {
//Does not cause a page reflow, but this solution isn't pretty.
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);
}
});
或者让父对象监听并告诉 View 何时渲染
var Layout = LayoutView.extend({
//...
onBeforeShow: function() {
//Does not cause a page reflow, but this solution isn't pretty.
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 that data changed", this.rerenderSubview);
this.containerRegion.show(this.layout);
},
rerenderSubview: function() {
this.containerRegion.show(this.layout, {forceShow: true});
}
});
最佳答案
在您需要采取行动的水平上聆听您的模型
当 View el
已经附加到 DOM 时,渲染会立即将 View 附加到 DOM,因此顶层 View 将立即附加到 DOM。这意味着如果您在 onRender 中有回调,它们将按顺序附加并且您将进行回流。
如果您改为将 subview 显示到 onBeforeShow 中,您将构建一个将显示一次的 View 树,假设顶层 View 已调用 show
。所以问题是在哪里调用顶级show
。我看到 2 个选项
简单选项
最简单的做法是让您的顶级 LayoutView 在 onRender
中显示它的 subview ,然后所有后续 subview 在 onBeforeShow
中显示它们的 subview 。这可能会导致一些绘画(顶层,然后是它显示的每个区域一个),但不会产生大量的绘画,并且可能不是性能问题(当然听起来你没有可见的性能问题。)
稍微复杂一点的选项
如果您真的只想在模型更改时重绘一次,那么您应该按照问题中的描述创建一个包装 View ,但不要让 subview 直接引用它,而是确保包装 View 具有对模型的引用,并让它在模型更改时重新显示您的布局。然后所有的回调都可以是 onBeforeShow
,更改将导致一次绘制。 View 之间不会有任何连接,所有内容都将在同一个回调中一致显示。
var LayoutContainer = LayoutView.extend({
initialize: function() {
this.listenTo(this.model,'change',this.reshowLayout);
},
reshowLayout: function() {
var layout = new Layout({
model: this.model,
container: this.containerRegion
});
this.containerRegion.show(layout);
}
});
关于javascript - 使用 Marionette 最大限度地减少回流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27925304/