javascript - 使用 Marionette 最大限度地减少回流

标签 javascript marionette

我有一个使用 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/

相关文章:

javascript - 如果在 IE 中的 body 元素上使用边距,则 Jquery offset 不会给出预期值

javascript - JavaScript 和 Jasmine 的不同构建

javascript - 尝试使用 HTML、css Bootstrap4 和 JavaScript 编写剪刀石头布游戏,无法让我的功能选择新图像工作

javascript - 我如何知道页面是否真的完全加载?

javascript - 如何在每个 Marionette View 渲染上记录消息?

backbone.js - Marionette.Layouts 可以在子区域之外拥有动态内容吗?

javascript - Marionette JS 和 Wreqr

JavaScript - 数组的逻辑问题

backbone.js - 主干路线发射两次

Backbone.js 在模型中设置 URL 参数并将其与 fetch 一起使用