【问题标题】:Ember View - Recursive view call throws Stop Script ErrorEmber View - 递归视图调用抛出停止脚本错误
【发布时间】:2015-03-13 04:39:52
【问题描述】:

我必须构建一个如下图所示的树结构。

为此,我使用 Ember 视图并递归调用以基于提供的模型构建整个树状结构。

我的模板是:

<script type="text/x-handlebars" data-template-name="index">
    <div class="zd-fldr fleft" style="width:230px;">   
        <ul class="fldr-sub">
            {{#each item in model}}
                {{view App.FoldertreeView model=item contentBinding="item"}}
            {{/each}}
        </ul>
    </div>
</script>

<script type="text/x-handlebars" data-template-name="foldertree">
    {{#if item.subfolder }}
        <span {{action 'getSubFolder' item}} {{bind-attr class="item.IS_OPENED:fdtree-icon:ftree-icon"}}> </span>
    {{else}}    
        <span class=""> </span>
    {{/if}}
    <span style="padding-top:20px;" class="fdetail fleft" >{{item.FOLDER_NAME}}</span>

    <ul style="margin-top:30px;" {{bind-attr class="item.IS_OPENED:showdiv:hidediv"}}>
        {{#each item in item.children}}
            {{view "foldertree" model=item contentBinding="item"}}
        {{/each}}
    </ul> 
</script>

JavaScript:

App.IndexRoute = Ember.Route.extend({
    model: function() {
        var treeArray = [];

        for(var i=0; i<4000; i++){
            var temp_obj = { 'FETCHED_DATA': false, 'FOLDER_ID': i, 'FOLDER_NAME': 'Folder_'+i, 'IS_OPENED': false, 'opened': true, 'subfolder': true, 'children': [] };
            treeArray.push(temp_obj);
        }
        return treeArray;
   } 
});

App.FoldertreeView = Ember.View.extend({
    tagName: 'li',
    templateName: 'foldertree',
    classNames: ['treediv', 's-fldr']
}); 

最初我通过调用 API 仅从服务器加载第一级文件夹。

然后当点击打开的节点时,通过向服务器调用请求来填充children数组。

现在当模型长度大于 3000 时,Firefox 浏览器会抛出“Stop Script”错误。

在我的树中,节点的数量没有限制。我该如何解决这个问题。

演示 JS Bin(在 Firefox 中试用)

【问题讨论】:

  • 你不觉得for循环循环太大了。我建议你保持小。以后可以根据需要添加或推送更多对象。
  • 我遇到了几乎相同的问题,尽管我使用的是局部视图而不是视图。还在追查。我怀疑这是 Ember/HBS 中的一个错误。
  • 我对你的问题感到困惑。您提到“递归”,但您发布的代码似乎只是在执行单级 4000 个元素,因此 {{#each item in item.children}} 循环将永远不会执行 AFAICT。您不是在测试 Ember 处理递归视图的能力,而是测试处理许多视图的能力。我自己用一个包含 10000 个元素的模型测试了 Ember,每个模型都使用一个视图显示,并且它很快就耗尽了 gas。构建视图的开销是巨大的。您可能想尝试使用局部变量。
  • @torazaburo 如果有子对象,它将被添加到将递归运行的子数组中。这样我就可以像所附图像一样拥有树状结构。现在渲染第一级模型本身(没有子对象)我得到了停止脚本错误。
  • 由于浏览量巨大,您遇到了停止脚本错误。如果我理解您要正确执行的操作,您应该对三个对象进行测试,每个对象都有三个孩子,依此类推,递归一些级别。这将分离出两个问题:(1) 递归视图是否正常工作,以及 (2) Ember 可以处理多少视图,与平面或嵌套无关。

标签: ember.js handlebars.js


【解决方案1】:

Ember 是一个网络框架。鉴于这些信息,您需要意识到如果不重用某些视图元素,您将无法在浏览器中有效地呈现 6000 个项目。甚至原生应用程序也不这样做:例如,在 iOS 中,TableView 中的单元格是可重用的,因此显示 6000 个项目集合的表格只有足够的单元格来覆盖视图的高度和一些滚动重叠。视图知道它的滚动位置,并呈现需要从集合中呈现的 10-20 个项目,当您向下滚动时,它会移除顶部元素,将元素放置在底部,并呈现下一个项目数据数组。这样,每个人都赢了。我建议你也这样做,因为 JS/HTML 无法有效地处理那么多元素。

我知道这不是一个有趣的实现,但是一旦你想出了一个第一次这样做的组件,你会很高兴你做到了。

荣誉奖:https://github.com/emberjs/list-view。你正在做一个文件树而不是一个列表,这比一个长列表更困难,但如果你稍微改变你的 UI,你仍然可以使用它。如果您的文件夹结构可通过树导航并在列表视图中显示文件,这可能会缓解您的问题,具体取决于问题是与多个文件还是多个文件夹有关。

【讨论】:

  • 感谢您的详细解释。我需要渲染只包含文件夹和子文件夹的长树结构。我将尝试延迟加载树渲染。
【解决方案2】:

这并不是真正的 Ember 问题,而是一般的 javascript 问题。当脚本需要很长时间才能执行时,浏览器会显示/触发此类错误消息,并且每个浏览器都不同。

您可以阅读this good blog post about long time runing scripts

如果您的浏览器环境受到控制(我的意思是您的计算机,我们的公司计算机),您仍然可以setup firefox to run longer scripts

然而,一个好的做法是在子任务中“拆分”您的脚本,从而减少执行时间。

编辑

在 cmets 中讨论过这是由于您生成的大量视图。您可以从后端返回 6000 个模型,但是一次生成 6000 个视图很繁重。

这是关于如何处理此问题的建议:http://jsbin.com/zakisoyesi/6/edit?html,js,output 供您免费使用,以适应您的用例和事件,通过使用 onScroll 或任何其他事件使其对用户透明。

【讨论】:

  • 我不同意这种分析。我认为这是 Ember/HBS 中的一个错误。
  • @torazaburo 您是否真的在 Firefox 和/或 chrome 中打开了脚本并查看了运行多少次?我做到了,显然脚本需要很长时间才能执行,这是根本问题......
  • @MrVinz 这不是一般问题。在我的演示中,我使用了通用 for 循环来构造对象并在模型中返回。 Ember 视图递归渲染模型并抛出脚本错误。
  • @Jeevi 递归函数或 for 循环都“阻塞”了执行,但显然不是 6000 个对象在循环中推送需要很长时间并杀死脚本,而是 ember 做了一些背后的魔力,如果您一次提供 6000 个对象,则需要时间来渲染。
  • @MrVinz 如果您签入 jsbin 链接,我已经计算了 for 循环所花费的时间。它只有大约 8 到 10 毫秒。 jsbin.com/qiqege/3/edit?html,js,output
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-22
  • 2015-08-02
  • 2011-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多