【问题标题】:CompositeView slow to render items for large result set MarionetteCompositeView 渲染大型结果集 Marionette 的项目很慢
【发布时间】:2014-10-12 01:25:37
【问题描述】:

我目前正在开发一个项目,该项目在后端使用 .NET MVC,在前端使用 Backbone (v1.1) 和 Marionette JS (v1.8.5),我在尝试渲染时遇到了一些性能问题具有 200 个结果或项目视图的复合视图。

我第一次遇到this SO post of a similar issue,它帮助我获得了更新版本的木偶(v1.8.5)。

Handlebars 模板用于显示一个 html 表格,其中每个 itemView 都包装在一个 tbody 中(其中有一个更复杂的手风琴视图,因此使用的是 tbody 而不是更具语义的 tr)

Composite 视图正在初始化,并在其子应用程序初始化时显示在 Marionette 区域中。

这是我的代码的简化版本。

活动子应用

'use strict';

App.module('Activities', function(){
    this.startWithParent = false;
});

App.addRegions({
    RegionActivities: '#region-Activities' // <= this lives in .NET View of project
});

App.Activities.addInitializer(function (options) {

    var module = this,
        activities = new Collections.Activities();

    module.activitiesView = new Views.ActivitiesView({
        collection: activities
    });

    App.RegionActivities.show(module.activitiesView);

    activities.fetch();

});

活动复合视图

'use strict';

Views.ActivitiesView = Backbone.Marionette.CompositeView.extend({

    template: Handlebars.templates['activities/activities'],

    itemView: Views.ActivityView,

    itemViewContainer: '.admin-table--activities', // <= html table that items are appended to

});

活动项目视图

'use strict';

Views.ActivityView = Backbone.Marionette.ItemView.extend({

    template: Handlebars.templates['activities/activity'],

    tagName: 'tbody'

});

我看了Marionette Docs on the better performing doc fragment

所以我遇到的性能问题是所有 200 个项目一次都被追加一个并且没有使用 docFragment 缓冲区。通过调试,我认为这是因为在获取之前使用空的活动集合实例化了视图,所以 Marionette 认为我正在更新集合并将 isBuffering 设置为 false。

我也尝试过像这样在获取成功回调中实例化活动视图;

activities.fetch({
    success: function(newCollection) {
        module.activitiesView = new Views.ActivitiesView({
            collection: newCollection
        });

        App.RegionActivities.show(module.activitiesView);
    }
});

这确实将 200 个项目附加到集合 elBuffer(大约需要 4 秒),但在屏幕上显示任何内容之前需要另外 50 秒左右。调试表明由集合触发的 onShow 方法可能会导致此延迟,因为它会逐个循环遍历每个项目。

我错过了什么吗?

我是否在正确的地方做所有事情?

我正在努力实现的目标是否可能?

我觉得很奇怪,这可能如此困难。

感谢您的宝贵时间。 汤姆

编辑

这里是复合视图和项目视图模板。

Activity CompositeView 模板

<table class="admin-table admin-table--accordion admin-table--activities">

    <colgroup>
        <col width="10%">
        <col width="22%">
        <col width="23%">
        <col width="23%">
        <col width="22%">
    </colgroup>

    <thead>
        <tr>
            <th>Type</th>
            <th>Vessel</th>
            <th>Activity</th>
            <th>Information</th>
            <th>Review Status</th>
        </tr>
    </thead>

</table>

Activity ItemView 模板(每个都包裹在 tbody 中)

<tr class="table-title">
    <td>Col 1 data</td>
    <td>Col 2 data</td>
    <td>Col 3 data</td>
    <td>Col 4 data</td>
    <td Col 5 data</td>
</tr>

<tr class="table-content">
    <td colspan="5">More info in here...</td>
</tr>

更新

chrome dev tools javascript CPU profile 的结果:

前 3 项均指 Marionette triggerMethod 占用 80% CPU。

全尺寸图片位于:http://i.stack.imgur.com/JjT3Z.png

【问题讨论】:

  • 你能发布模板吗?这应该没什么区别,但试试activities.fetch().done(function() { App.RegionActivities.show(module.activitiesView); })
  • 感谢@Meistro,但不幸的是这并没有帮助。我现在正在使用我的问题中的第二个版本,我在其中执行提取,然后成功实例化视图。 Console.logging activiesView 实例发生在第二次。问题似乎与在屏幕上呈现集合有关。主要通过 region.show()
  • 你能发布你的onShow函数吗?我不明白为什么调用该函数几百次会导致您出现问题(50 秒延迟)。您的模板似乎也很简单。我有一个应用程序,它非常相似地插入了 200 项长的列表,并且看不到您遇到的那种性能问题。这个等式缺少一些东西。
  • 另外,当您深入了解配置文件的triggerMethod 部分时,您要获得什么功能,这是您自己的代码?
  • @AndrewHubbs 我没有在我的复合视图或项目视图中使用 onShow 函数。关于 devtools 配置文件,我会回复你。我从记忆中没有注意到与我自己的代码有关的任何内容

标签: javascript performance backbone.js marionette backbone-views


【解决方案1】:

当集合被重置时,缓冲区将被使用,所以你可以尝试

activities.fetch({reset: true});

另一种选择是等到获取完成(使用延迟/承诺)后再初始化和显示您的视图。

【讨论】:

  • 感谢@david-sulc,但这并没有奏效。是的,它在我的复合视图上触发了重置事件,但结果仍然需要大约 1 分钟才能在屏幕上呈现。我将使用向下钻取的 cpu 配置文件更新问题。
猜你喜欢
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 2015-11-28
  • 2013-10-14
  • 1970-01-01
  • 2014-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多