草庐IT

javascript - 嵌套ng-repeat导致浏览器卡顿如何处理

coder 2024-05-09 原文

我创建了一个可能有 1 - 5000 个项目的嵌套树,我能够让它工作,但它在显示树之前卡住了我的浏览器\加载微调器几秒钟。

我怎样才能使它流畅以使浏览器永远不会卡住?

我怎么知道 angularjs 何时完成创建或渲染或计算(不确定正确的词)整个列表,以便我可以删除加载微调器,如您所见范围。$last 不起作用因为我们已经嵌套了 ng-repeat 并且对于 scope.$parent.$last

这是我创建的 plunker,但带有演示数据 -

http://plnkr.co/edit/GSZEpHjt5YVxqpg386k5?p=preview

示例数据集 - http://pastebin.com/YggqE2MK

在这个例子中并不算太糟糕,但在我的 OWN 设置和所有其他组件中,我的浏览器有时会卡住大约 4000 个项目超过 10 秒。

我已经考虑过的

  • 使用了 bindonce.js 库,但不太成功
  • 再次使用“::”单一绑定(bind)但没有成功
  • 仅在用户展开类别时加载第一级然后渲染下一级,但我的树可能非常随机,也许我只有 1 个单根节点和 100 多个子节点
  • 分页不适合场景

HTML

  <script type="text/ng-template" id="tree_item">
    <div ng-init="category.expanded=true">
      <div ng-class="{'selected': category.ID==selectedCategoryID}">
        <div class="icon icon16" ng-if="category.Children.length>0" ng-click="$parent.category.expanded=!$parent.category.expanded" ng-class="$parent.category.expanded?'col':'exp'"></div>
        <div class="icon icon-category" ng-class="'icon-category-'+category.TypeType" ng-style="{'border-color':category.Colour}" ng-attr-title="{{category.Status?Res['wpOPT_Status'+category.Status]:''}}"></div>
        <a ng-href="#id={{category.ID}}" ng-class="{'pending-text': category.PendingChange}">{{category.Name}}</a>
      </div>
      <ul class="emlist" ng-show="category.expanded">
        <li ng-repeat="category in category.Children | orderBy:'Name'" ng-include="'tree_item'" ng-class="{'selected': category.ID==selectedCategoryID}" e2-tree-item is-selected="category.ID==selectedCategoryID">
        </li>
      </ul>
    </div>
  </script>

  <div id="CategoryListContainer" class="dragmenu-container initial-el-height">
    <div class="spinner" data-ng-show="status=='loading'"></div>
    <ul id="CategoryList" class="dragmenu-list ng-cloak" ng-show="status=='loaded'">
      <li ng-repeat="category in tree | orderBy:'Name'" ng-include="'tree_item'" e2-tree-item is-selected="category.ID==selectedCategoryID"></li>
    </ul>
  </div>

JS

var app = angular.module('recursionDemo', []);

app.controller("TreeController", function($scope, $timeout) {
  $scope.status = "loading";

  $timeout(function() {
        var result = {
      "GetCategoryTreeResult": [{ // too big data set so I pasted it here http://pastebin.com/YggqE2MK }];
    $scope.tree = result.GetCategoryTreeResult;

    $scope.status = "loaded";
  }, 3000);
});

app.directive('e2TreeItem', function($timeout) {
  function link(scope, element, ngModel) {
    scope.$watch('isSelected', function(oldVal, newVal) {
      if (scope.isSelected === true) {
        element.parentsUntil('#CategoryListContainer', 'li').each(function(index, item) {
          angular.element(item).scope().category.expanded = true;
        });
      }
    });

    // not working
    //if (scope.$parent.$last) {
    //  console.log("last has been caught");
    //  var appElement = document.querySelector('[ng-app=recursionDemo]');
    //  angular.element(appElement).scope().status = "loaded";
    //}
  }
  return {
    link: link,
    scope: {
      isSelected: '=?'
    }
  };
});

最佳答案

更新:

演示:http://plnkr.co/edit/bHMIU8Mx5grht9nod1CW?p=preview

您可以通过更改 app.js 的 L10901 来顺利加载数据,如下所示。但是你应该注意到,如果你仍然想按名称排序,并希望它稳定,你应该只对源数据进行排序,而不是使用“order by”进行 Angular 排序。 (你想要一些代码来对源数据进行排序吗?)

    function getDataGradually(data, childKey, gap, count, updateCb, finishCb) {
        const lastPositon = [];
        const linearData = [];
        const ret = [];


        function getLinearData(arr, position) {
            arr.forEach(function (obj, index) {
                const pos = position.concat([index]);
                if (obj[childKey] && obj[childKey].length) {
                    var children = obj[childKey];
                    obj[childKey] = [];
                    linearData.push({
                        obj,
                        pos
                    });
                    getLinearData(children, pos);
                } else {
                    linearData.push({
                        obj,
                        pos
                    });
                }
            });
        }
        getLinearData(data, []);

        function insertData({
            obj,
            pos
        }) {

            let target = ret;
            pos.forEach(function (i, index) {


                if (index === pos.length - 1) {
                    target[i] = obj;

                } else {
                    target = target[i][childKey];
                }
            });

        }
        let handled = 0;

        function doInsert() {
            let start = handled;
            let end;
            if (handled + count > linearData.length) {
                end = linearData.length;
            } else {
                end = handled + count;
            }
            for (let i = start; i < end; i++) {
                insertData(linearData[i]);
            }
            handled += count;
            if (handled < linearData.length) {
                setTimeout(function () {
                    doInsert();
                    updateCb && updateCb();
                }, gap);
            } else {
                finishCb && finishCb();
            }
        }
        doInsert();



        return ret;
    }

    $scope.tree = getDataGradually(result.GetCategoryTreeResult, "Children", 0, 30, function () {
      $scope.$digest();
    }, function () {
      //finished 
    });
    //$scope.tree = result.GetCategoryTreeResult;
    $scope.status = "loaded";
  }, 3000);

旧答案:

您可以使用$timeout 获取渲染时间。尝试更改 app.js 的 L10901,如下所示。

        $scope.tree = result.GetCategoryTreeResult;
        console.time("A")
        $timeout(function(){
          console.timeEnd("A");
        });
        $scope.status = "loaded";
      }, 3000);

顺便说一句,我的电脑上出现“1931.881ms”。

关于javascript - 嵌套ng-repeat导致浏览器卡顿如何处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42552198/

有关javascript - 嵌套ng-repeat导致浏览器卡顿如何处理的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  3. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  4. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  5. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  6. ruby-on-rails - 使用回形针的嵌套形式 - 2

    我有一个名为posts的模型,它有很多附件。附件模型使用回形针。我制作了一个用于创建附件的独立模型,效果很好,这是此处说明的View(https://github.com/thoughtbot/paperclip):@attachment,:html=>{:multipart=>true}do|form|%>posts中的嵌套表单如下所示:prohibitedthispostfrombeingsaved:@attachment,:html=>{:multipart=>true}do|at_form|%>附件记录已创建,但它是空的。文件未上传。同时,帖子已成功创建...有什么想法吗?

  7. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  8. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  9. ruby - 如何根据长度将路径数组转换为嵌套数组或散列 - 2

    我需要根据字符串路径的长度将字符串路径数组转换为符号、哈希和数组的数组给定以下数组:array=["info","services","about/company","about/history/part1","about/history/part2"]我想生成以下输出,对不同级别进行分组,根据级别的结构混合使用符号和对象。产生以下输出:[:info,:services,about:[:company,history:[:part1,:part2]]]#altsyntax[:info,:services,{:about=>[:company,{:history=>[:part1,:pa

  10. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

    我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

随机推荐