长数组列表渲染使 Angular.js 中的页面滚动变慢
Posted
技术标签:
【中文标题】长数组列表渲染使 Angular.js 中的页面滚动变慢【英文标题】:Long array list rendering makes page scrolling slow in Angular.js 【发布时间】:2017-06-25 14:51:50 【问题描述】:当尝试从一个数组(带有图像)呈现超过 120 个项目时,列表的滚动会变慢。基本上,当我在无限滚动中加载新数据时,我将旧数组数据与新数组数据连接起来。
另一方面,像 dribbble、behance 这样的流行网站似乎没有这个问题。也许这个问题是 Angular.js 特有的?有人在他们的项目中遇到过这个问题吗?
【问题讨论】:
这里要了解的要点是您是从服务器还是本地加载数据?如果它在本地,您可以使用 limitTo 过滤而不是连接 也许看看像ngInfiniteScroll 这样的指令来逐步加载您需要的项目,而不是一次全部加载 当我使用ng-repeat
但没有track by
渲染一个庞大的数组时,我遇到了这种情况。看看你是否错过了
如果您正在寻找提高性能的技巧,这是我之前发布的一篇文章,其中讨论了您可以尝试的一些事情:***.com/a/38349146/841804
ng-repeat 很棒,但是当 Array 有超过 20-30 个元素时,它会变得非常缓慢。我在某处读到是因为在每次更新中重新渲染所有项目。您可以尝试使用一次性绑定,但它只提供一点帮助。当我们构建 Chat App 而不是 Angular 的 ng-repeat 时,我们必须使用纯 JS 来列出消息。
【参考方案1】:
ANGULARJS 中的无限滚动
不需要任何额外的插件。
app = angular.module("demo", []);
app.controller("MainController", function($scope, $http)
// the array which represents the list
$scope.items = ["1. Scroll the list to load more"];
$scope.loading = true;
// this function fetches a random text and adds it to array
$scope.more = function()
$http(
method: "GET",
url: "https://baconipsum.com/api/?type=all-meat¶s=2&start-with-lorem=1"
).success(function(data, status, header, config)
// returned data contains an array of 2 sentences
for(line in data)
newItem = ($scope.items.length+1)+". "+data[line];
$scope.items.push(newItem);
$scope.loading = false;
);
;
// we call the function twice to populate the list
$scope.more();
);
// we create a simple directive to modify behavior of <ul>
app.directive("whenScrolled", function()
return
restrict: 'A',
link: function(scope, elem, attrs)
// we get a list of elements of size 1 and need the first element
raw = elem[0];
// we load more elements when scrolled past a limit
elem.bind("scroll", function()
if(raw.scrollTop+raw.offsetHeight+5 >= raw.scrollHeight)
scope.loading = true;
// we can give any function which loads more elements into the list
scope.$apply(attrs.whenScrolled);
);
);
li
display:block;
list-style-type:none;
margin-bottom: 1em;
ul
height:250px;
background: #44E394;
color: #fff;
overflow:auto;
width:550px;
border-radius: 5px;
margin:0 auto;
padding: 0.5em;
border: 1px dashed #11BD6D;
&::-webkit-scrollbar
width:8px;
background-color:transparent;
;
&::-webkit-scrollbar-thumb
background-color:#b0fccd;
border-radius:10px;
&::-moz-scrollbar
width:8px;
background-color:transparent;
;
&::-moz-scrollbar-thumb
background-color:#b0fccd;
border-radius:10px;
&::-ms-scrollbar
width:8px;
background-color:transparent;
;
&::-ms-scrollbar-thumb
background-color:#b0fccd;
border-radius:10px;
body
text-align:center;
font-size:1.2em;
font-family: "Helvetica";
color: #44E394;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAG0lEQVQIW2P88OHDfwY0wAgSFBAQYEQWp1AQAKUbE9XRpv7GAAAAAElFTkSuQmCC) repeat;
padding: 2em;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app='demo'>
<div data-ng-controller='MainController'>
<ul class='hello' when-scrolled='more()'>
<li data-ng-repeat='item in items'>
item
</li>
</ul>
<div data-ng-show='loading'>Loading</div>
</div>
</div>
<h1>INFINITE SCROLLING IN ANGULARJS</h1>
【讨论】:
这应该是答案!鉴于指令实施略有变化但很好的答案,解决滚动列表问题的更好方法。【参考方案2】:ngInfiniteScroll
只是一个指令,可以用来实现无限滚动,不会影响这个问题。
以下是一些加快应用程序速度的提示
尽可能避免在重复部分使用观察者
使用一次性绑定:::model
使用ng-*
减少:所有这些都添加了$watch。
使用$watchCollection
或$watch
减少
使用 ng-if
而不是 ng-show
:它会删除 dom 并销毁其中的观察者。
使用track by
:对于大型集合,这会显着提高渲染性能。
在串联中:
你可以看到your problem in plunker 和下一个命令
[].push.apply($scope.list,getNewList());
优于
$scope.list=$scope.list.concat(getNewList());
但是以上所有提示都可以让用户在列表中拥有更多项目,但是当列表中的项目数量超过(比如说 1000)时,滚动会再次变慢
对于这个问题,我们可以使用 Angular Material md-virtual-repeat,它只是按需加载可见项目,就像我在 your problem with virtual repeat 中使用的那样。
【讨论】:
【参考方案3】:我认为您应该考虑优化您的应用程序,而不仅仅是选择更好的指令或插件,太多的作用域也会降低应用程序的速度。
【讨论】:
以上是关于长数组列表渲染使 Angular.js 中的页面滚动变慢的主要内容,如果未能解决你的问题,请参考以下文章
微信小程序开发——列表渲染 & 条件渲染 & tabBar & 页面跳转
从另一个页面添加数据库(couchbase)中的项目后,如何从 angular.js 中的页面更新列表?