当我有很多行时,有没有办法加速我的网格反应的方式?

时间:2014-09-09 10:20:39

标签: angularjs

我有代码创建这样的网格:

<div ng-repeat="row in home.grid.data track by row.examId">
   <div>{{ row.examId }}</div>
   <div>xxxx</div>
</div>

我有更多的专栏。

有没有办法可以加快页面反应的方式?好像什么时候 我在网格中有很多数据,然后页面反应缓慢。会吗 如果我在row.examId的输入类型字段中使用ng-model,那就有所作为。注意 可以编辑后面的一些字段,但大多数只是显示。

3 个答案:

答案 0 :(得分:4)

我相信 bindonce 完全符合您的需求。

通过减少观察者数量,它可以使页面变得更具响应性。检查他们的 demos

答案 1 :(得分:4)

这就是我所做的。有两种方法。无论两种解决方案如何,都使用bindOnce。请留意页面上观察者的数量。看看这个解决方案的结尾 - 如何跟踪页面上的观察者。

我添加了一个解决方案3,这很棒,造型有点困难

解决方案1:

使用绑定一次的分页控件。

解决方案2 这对我有用,而且非常优雅。您重复bindonce,然后实现无限滚动。我跟着this blog post,它就像一个魅力。我们的想法是限制行数并在滚动时更改限制。

ng-repeat="item in items | orderBy:prop | filter:query | limitTo:limit"

基本上,你的HTML看起来像这样。我修改了OP的代码以使用bindonce。

 <div id="estates-listing"  extend-height>
  <div class="content" infinite-scroll="addMoreItems()" infinite-scroll-distance="2">
    <div class="content-wrapper">
      <div class="house" bindonce="estate" ng-animate="'animate'" ng-class="{inactive: (selectedEstate != null || selectedEstate != undefined) && estate.id!=selectedEstate.id , active:(selectedEstate != null || selectedEstate != undefined) && estate.id==selectedEstate.id}" ng-repeat="estate in estates | orderBy: orderProp : orderReverse | limitTo: config.itemsDisplayedInList track by estate.id" ng-mouseover="highlightMarker(estate)" ng-mouseleave="leaveMarker(estate)" ng-click="showDetailview(estate.id)" >
        <div id="l-el{{estate.id}}">
        </div>
      </div>
    </div>
  </div>
</div>

这是帖子中的无限滚动指令。将此添加到您的应用程序,请不要使用bower安装使用标准无限滚动。

app.directive('infiniteScroll', [
  '$rootScope', '$window', '$timeout', function($rootScope, $window, $timeout) {
    return {
      link: function(scope, elem, attrs) {
        var checkWhenEnabled, handler, scrollDistance, scrollEnabled;
        $window = angular.element($window);
        elem.css('overflow-y', 'scroll');
        elem.css('overflow-x', 'hidden');
        elem.css('height', 'inherit');
        scrollDistance = 0;
        if (attrs.infiniteScrollDistance != null) {
          scope.$watch(attrs.infiniteScrollDistance, function(value) {
            return scrollDistance = parseInt(value, 10);
          });
        }
        scrollEnabled = true;
        checkWhenEnabled = false;
        if (attrs.infiniteScrollDisabled != null) {
          scope.$watch(attrs.infiniteScrollDisabled, function(value) {
            scrollEnabled = !value;
            if (scrollEnabled && checkWhenEnabled) {
              checkWhenEnabled = false;
              return handler();
            }
          });
        }
        $rootScope.$on('refreshStart', function(event, parameters){
            elem.animate({ scrollTop: "0" });
        });
        handler = function() {
          var container, elementBottom, remaining, shouldScroll, containerBottom;
          container = $(elem.children()[0]);
          elementBottom = elem.offset().top + elem.height();
          containerBottom = container.offset().top + container.height();
          remaining = containerBottom - elementBottom ;
          shouldScroll = remaining <= elem.height() * scrollDistance;
          if (shouldScroll && scrollEnabled) {
            if ($rootScope.$$phase) {
              return scope.$eval(attrs.infiniteScroll);
            } else {
              return scope.$apply(attrs.infiniteScroll);
            }
          } else if (shouldScroll) {
            return checkWhenEnabled = true;
          }
        };
        elem.on('scroll', handler);
        scope.$on('$destroy', function() {
          return $window.off('scroll', handler);
        });
        return $timeout((function() {
          if (attrs.infiniteScrollImmediateCheck) {
            if (scope.$eval(attrs.infiniteScrollImmediateCheck)) {
              return handler();
            }
          } else {
            return handler();
          }
        }), 0);
      }
    };
  }
]);

解决方案3: 冒险并使用UI-Grid,UI Grid是新的ng-grid。它不是生产准备好的,但是我们正在制作一张桌子,我们有超过1000条记录 - 开箱即用它非常棒。这些教程很广泛,但没有多少SO支持。它内置虚拟化,因为它是ng-grid的扩展,它具有很多向后兼容性。以下是10,000 rows

的示例

页面上的观察人数: 这是一个跟踪页面上观察者数量的功能。拇指规则永远不会超过2500观察者,但我们将自己局限于&lt; 1000。

 $scope.TotalWatchers = function () {
                var root = $(document.getElementsByTagName('body'));
                var watchers = 0;

                var f = function (element) {
                    if (element.data().hasOwnProperty('$scope')) {
                        watchers += (element.data().$scope.$$watchers || []).length;
                    }

                    angular.forEach(element.children(), function (childElement) {
                        f(angular.element(childElement));
                    });
                };

                f(root);

                return watchers;
            };

答案 2 :(得分:1)

我发现帮助执行大型表的最重要的事情是限制事件绑定到父对象,并利用冒泡来捕获子进程的事件。

如果是父母,您可以获得哪个目标被击中。我使用以下代码。

obj.onclick = function (e) {
    e = window.event || e;
    var t = e.target || e.srcElement;
}

在这种情况下,e是您的常规事件对象,t是事件冒泡前的初始目标对象。你需要使用t作为&#39;这个&#39;引用事件绑定的对象而不是触发事件的对象。

我使用的代码是一个非常大的表,它通过将事件移动到静态的父节点,将表的渲染时间减少了近80%。如果您需要更新内容,这也会有所帮助,因为您不必重新绑定任何事件。

希望这有帮助。