参考网址:1、http://www.csdn.net/article/2013-09-18/2816972-AngularJS-performance-tuning-for-long-list
2、http://developer.51cto.com/art/201309/411277.htm
参考资源 2,
AngularJS 中的ng-repeat在处理大型列表时,速度为什么会变慢?
AngularJS中的ng-repeat在处理2500个以上的双向数据绑定时速度会变慢。这是由于AngularJS通过“dirty checking”函数来检测变化。每次检测都会花费时间,所以包含复杂数据结构的大型列表将降低你应用的运行速度。当然如果列表纯显示,不需要双向绑定,只需要单向绑定,也可以解决卡顿的问题,但是如果列表每一个字段都是需要动态改变的,如:大型会议控制列表,每一个终端都是需要控制10几个按钮,改变终端的连接、视频、语音、分屏等配置,并且实时更新,就必须要双向绑定了。因此只能通过以下两种方式解决:缓解该问题,最好的办法是限制所显示列表的大小。可通过分页、添加无限滚动条来实现。(我没用过添加无限滚动条,个人觉得回滚时也是会卡顿的,并且项目需求是滚动显示并且不卡顿,因此使用了一种假装无限滚动,实际分页的方式)
一、参考分页原理
分页,我们可以使用AngularJS的“limitTo”过滤器(AngularJS1.1.4版本以后)和“startFrom”过滤器。可以通过限制显示列表的大小来减少渲染时间。这是减少渲染时间最高效的方法。但是,我用过这种方式不大好处理数据,因为startFrom 和limitto是把源数据A截取出某一部分子集B出来显示,那下次回滚时,上一页就需要重新把A再截取一部分出来赋给B,还有双向绑定的基础是数据源不变,因为B不能是A的子集,B只能是指向A的某一部门的变量指针。这就需要把数据源A分成多个组,也就是多页,如B=[[A[0],A[1]],[A[2],A[3]],[A[4],A[5]],[A[6],A[7]],......[A[n-1],A[n]]],显示的列表就是B[currentpage], currentpage =0,1,2,3,...这样就可以改动最小,保证数据源还是A一个,实时更新的也是A,排序的也是A。B只是一个指向A的某一部分。用于显示,操作的也是A的元素。
二、参考无线滚动原理
滚动,当滚动条滚动到底部时,就替换当前显示的数据B[currentpage],改成B[currentpage+1],当滚到顶部时,就B[currentpage-1],因此只需绑定$scope.currentpage动态改变即可实现。
$scope.initScrollPage = function () { $scope.scrollPageConfig.currentPage = 0; $scope.raw.scrollTop = 0; $scope.currentStart = 1; $scope.currentEnd = parseInt( $scope.raw.clientHeight/85) +1; }; var lastScrollTop = 0; $('#parListDiv').bind('scroll', function(e) { var st = $scope.raw.scrollTop; $scope.currentStart = 1 + $scope.scrollPageConfig.pageSize * $scope.scrollPageConfig.currentPage + parseInt( $scope.raw.scrollTop/85); $scope.currentEnd = parseInt( $scope.raw.clientHeight/85) +$scope.currentStart; if (st > lastScrollTop){ if ($scope.raw.scrollTop + $scope.raw.offsetHeight > $scope.raw.scrollHeight && $scope.scrollPageConfig.totalPage > $scope.scrollPageConfig.currentPage+1) { console.log($scope.raw.scrollTop + $scope.raw.offsetHeight,$scope.raw.scrollHeight); console.log("向下滚动"); $scope.raw.scrollTop = 10; $scope.scrollPageConfig.currentPage ++; e.stopPropagation(); } }else if(st <lastScrollTop){ if ($scope.raw.scrollTop == 0 && $scope.scrollPageConfig.currentPage != 0) { console.log("向上滚动"); if($scope.scrollPageConfig.currentPage == $scope.scrollPageConfig.totalPage-1){ $scope.raw.scrollTop = 200; $scope.raw.scrollHeight = $scope.scrollPageConfig.pageSize * 85; }else{ $scope.raw.scrollTop = $scope.scrollPageConfig.pageSize * 85 - $scope.raw.offsetHeight -10; } if($scope.scrollPageConfig.currentPage > 0)$scope.scrollPageConfig.currentPage --; e.stopPropagation(); } } lastScrollTop = st; });
//重组显示的与会者,分组防止卡顿 $scope.initShowParListData = function () { if (!!$scope.searchCoade) {//搜索的数据源 $scope.scrollPageConfig.dataResource = $filter('orderBy')($filter('changeGroupByDoubleConditionsFilter')($scope.aParticipantOrginalData,['name','displayName','address'] ,$scope.searchCoade), $scope.order); } else { $scope.scrollPageConfig.dataResource = $filter('orderBy')($scope.aParticipantOrginalData, $scope.order); } $scope.showParList = []; //1、如果列表数比一页的数量少时,直接把数据源放进显示数组即可 if ($scope.scrollPageConfig.dataResource.length <= $scope.scrollPageConfig.pageSize) { $scope.showParList.push($scope.scrollPageConfig.dataResource); } else {//2、列表数据大于一页,就分页存入数组 var k, len; var temp = []; var count = 0; for (k = 0, len = $scope.scrollPageConfig.dataResource.length; k < len; k++) { temp.push($scope.scrollPageConfig.dataResource[k]); if (temp.length == $scope.scrollPageConfig.pageSize) { $scope.showParList.push(temp); temp = []; count++; } } var floatTotal = $scope.scrollPageConfig.dataResource.length/$scope.scrollPageConfig.pageSize; var intTotal = parseInt($scope.scrollPageConfig.dataResource.length/$scope.scrollPageConfig.pageSize); var isFloat = (floatTotal - intTotal)>0; $scope.scrollPageConfig.totalPage = isFloat? intTotal + 1 :intTotal; if (!!temp) {//分页,最后一页多余的数据 if(temp.length < parseInt($scope.scrollPageConfig.pageSize/2)){ $scope.showParList[ $scope.showParList.length -1] = $scope.showParList[ $scope.showParList.length -1].concat(temp); $scope.scrollPageConfig.totalPage -= 1; }else{ $scope.showParList.push(temp); } } } // console.log($scope.showParList); };