手机端优化列表滚动性能——分页加载

现在在手机端列表滚动随处可见,拿现在大家都在用的微信来说,朋友圈就是一个列表,和好友发信息界面就是一个列表。

如果列表长度不长,比如你微信朋友圈一共就只有两三个人分享过他们的动态,那没问题,如果你是大屏手机估计还不用滚动就已经看完了。

但那有可能吗?有也只是少数。我们现在每天刷朋友圈那都是几屏几屏这样刷的。

我们设定一屏有五个人分享的动态,每一个动态里面有5个dom节点,即一屏有25个dom节点。

我们开始刷朋友圈,才看了四屏就已经100个节点了,再往下刷成百甚至上千个dom节点都出来了,那你手机岂不是卡成翔了。

但我们现实中刷朋友圈会越往下刷越卡吗?不会。为什么呢?

这就是今天要说的一个优化手机端列表滚动性能的方法——分页加载

什么是分页加载呢,大致意思就是把一个列表分成很多很多页,我一开始只给你显示若干页(N),当我往下滚动到底部的时候,显示下一页,同时把最上面那一页移除。

同样道理,往上滚动时则显示上一页,同时把最下面那一页移除。这样,显示的就永远只有N页,dom节点也就永远只有Nx25个。

那么分页加载需要处理哪些问题呢?

1. 往下滚动的时候把最上面一页移除,那等我要往上滚动的时候,上一页都已经被移除掉了,我怎么获取到上一页的内容呢?

2. 既然有dom节点的移除和添加,那么我的滚动条位置要移除页面的同时要怎么设置才能让用户看起来像是无缝连接呢?

3. 我如何判断我已经滚动到了页面的顶部或底部?

4. 在滚动到底部或顶部的时候,我们具体究竟要执行哪些操作。

我们一个个来解决。

第一个问题我们只需要用两个数组来存取被移除掉的内容就OK了。

var preRemoveArray = []; //被移除的当前页面之前的页面
var nextRemoveArray = []; //被移除的当前页面后面的页面

当我们要移除上一页的时候,只需要获得第一页的html,将它push进preRemoveArray就可以了。同时如果nextRemoveArray中有内容的话(意味着你之前已经浏览过下面的内容),只需要执行

nextRemoveArray.pop(nextRemoveArray.length - 1);

就可以获取到下一页的内容了

第二个问题,关于滚动条的位置,我们分两种情况。

1.往下拉

我们通过document.body.scrollTop获得当前滚动条的位置,因为往下拉要移除第一页的内容,所以

document.body.scrollTop = document.body.scrollTop - 第一页的高度

2.往上拉

假设我们现在页面中显示的是第2、3页,此时滚动到顶部,document.body.scrollTop = 0,加载了上一页的内容,移除了第3页之后,页面中显示的是第1、2页,

我们的滚动条要设置在第2页的顶部,这样用户看起来才像是无缝连接的,所以

document.body.scrollTop = document.body.scrollTop + 第一页的高度

3.判断是否到顶部很简单

var isTop = function() {
    return document.body.scrollTop === 0;
};

返回true就是到顶部了

判断是否到底部需要获取几个值,

一个是document.body.scrollTop,当前滚动条的位置

一个是window.screen.height,当前屏幕的高度

一个是document.body.clientHeight, 当前整个页面的总高度

只有当document.body.scrollTop + window.screen.height = document.body.clientHeight时,即

var isBottom = function() {
    return document.body.scrollTop + window.screen.height == document.body.clientHeight;
};

返回true时,则滚动到了底部。

4. 在滚动到顶部的时候,我们需要判断preRemoveArray里是否有值,有则意味着前面有页面,没有则意味着这是第一页,第一页的话我们不需要做任何处理。

如果不是第一页的话,我们要执行

1). 获取当前列表中的最后一页,并存进nextRemoveArray数组里

2). 将上一页的内容添加进列表中

3). 设置滚动条的位置

4). 将最后一页移除

往下滚动也是同一个道理,只是无论nextRemoveArray里面是否有值我们都要进行相应的操作。

有值则去nextRemoveArray里上一页的内容添加进列表

没有值则生成新的节点,添加到列表中。

最终代码如下:

var PAGE = 1; //初始化页数
var PAGESIZE = 5; //每页展示几条数据

var $list = $(‘#list‘); //列表

var preRemoveArray = []; //被移除的当前页面之前的页面
var nextRemoveArray = []; //被移除的当前页面后面的页面

var init = function() {
    initPage();
    initEvent();
};

var initPage = function() {
    renderData();
};

var initEvent = function() {
    var $page;
    var length;
    window.onscroll = function() {
        if (isTop()) {
            if (preRemoveArray[0]) {
                length = preRemoveArray.length;
                $page = $($(‘.page‘)[$(‘.page‘).length - 1]); //获取当前列表中显示的最后一页
                nextRemoveArray.push($page[0].outerHTML); //将最后一页内容数组
                $list.prepend(preRemoveArray.pop(length - 1)); //将上一页内容添加进列表
                document.body.scrollTop = document.body.scrollTop + $($(‘.page‘)[0]).height(); //设置滚动条位置
                $page.remove(); //移除最后一页
            }
        } else if (isBottom()) {
            $page = $($(‘.page‘)[0]); //获取当前列表中显示的第一页
            preRemoveArray.push($page[0].outerHTML); //将第一页内容数组

            if (nextRemoveArray[0]) { //如果已经浏览过下面的内容
                length = nextRemoveArray.length;
                $list.append(nextRemoveArray.pop(length - 1)); //将下一页内容添加进列表
            } else { //如果没有浏览过下面的内容
                renderSinglePage();
            }

            document.body.scrollTop = document.body.scrollTop - $page.height(); //设置滚动条位置
            $page.remove(); //移除第一页
        }
    };
};

var renderData = function() {
    var innerHTML = ‘‘;

    //我设定它永远只显示两页,所以一开始先加载两页数据出来
    for (var i = 0; i < 2; i++) {
        innerHTML += getData();
    }

    $list.append(innerHTML);
};

var renderSinglePage = function() {
    var innerHTML = ‘‘;
    innerHTML += getData();
    $list.append(innerHTML);
};

var getData = function() {
    var innerHTML = ‘‘;
    innerHTML += ‘<div class="page page-‘ + PAGE + ‘">‘;

    for (var i = 0; i < PAGESIZE; i++) {
        innerHTML += ‘<li>‘ + PAGE + ‘</li>‘; //为方便看的清楚,我们给每行数据标记它是属于第几页的
    }

    innerHTML += ‘</div>‘;
    PAGE++;

    return innerHTML;
};

var isBottom = function() {
    return document.body.scrollTop + window.screen.height == document.body.clientHeight;
};

var isTop = function() {
    return document.body.scrollTop === 0;
};

init();

PS: 为了方便开发,上面的代码引入了zepto.js

时间: 2024-10-15 14:37:26

手机端优化列表滚动性能——分页加载的相关文章

jQuery手机端上拉刷新下拉加载更多页面

<!doctype html> <html> <head> <title>jquery 手机端上拉刷新下拉加载更多页面</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta name="viewpost" content="width=device-wi

基于Android官方AsyncListUtil优化改进RecyclerView分页加载机制(一)

基于Android官方AsyncListUtil优化改进RecyclerView分页加载机制(一) Android AsyncListUtil是Android官方提供的专为列表这样的数据更新加载提供的异步加载组件.基于AsyncListUtil组件,可以轻易实现常见的RecyclerView分页加载技术.AsyncListUtil技术涉及的细节比较繁复,因此我将分别写若干篇文章,分点.分解AsyncListUtil技术. 先给出一个可运行的例子,MainActivity.java: packag

优化UITableView滚动性能

自定义的cell如下: 第一个:Instruments测试,iphone4 38fps-45fps,iphone3G 25fps // table with normal XIB based cells - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"CustomC

iOS 高效的分页加载(TableView、CollectionView)

一.tableview的分页加载的代码对比 没有优化之前的代码如下 [strongSelf.tableView.mj_footer endRefreshing]: [strongSelf.articleArr addObjectsFromArray:feedList]; [strongSelf.tableView reloadData]; 优化之后的代码 NSMutableArray *indexPaths = [NSMutableArray array]; [feedList enumerat

asp.net网站开发中用jquery实现滚动浏览器滚动条加载数据(类似于腾讯微博)

自从腾讯微博上线以来,基本上就开始用了,一直到现在,作为一个开发人员,也看到了腾讯微博一直在不停的改变,也不知道大家有没有发现,腾讯微博提供两种加载数据的方式,一种是分页,一种是滚动浏览器滚动条加载数据,分页功能我想大家都做得太多了,今天我与大家分享一下我用滚动条滚动加载数据,小生不才,还望各位大侠指教,呵呵~ 下面开讲: 首先说一下思路,我用的是Jquery,然后通过Jquery的ajax()方法通过 HTTP 请求加载远程数据来实现的,用到Jquery,首先要应用jquery.min.js类

移动端下拉分页加载插件dropload.js

一.dropload.js下载地址: http://www.jq22.com/jquery-info6960 该地址有dropload.js的基础说明文档,下载的压缩包有相应的demo 二.依赖 Zepto 或者 jQuery 1.7以上版本,推荐jQuery 2.x版本(二者不要同时引用) Zepto or jQuery 1.7+,recommend to use jQuery 2.x(not use them at the same time) 三.bug及解决方案 1.小屏手机不加载问题

[android] 瀑布流布局——分页加载(详细代码)

效果是这个样的: 布局思路: 最外层父窗体是一个RelativeLayout(图里没画出来),从内层开始. 黑色:自定义ScrollView 红色:LinearLayout,为了盛放内层三个布局,orientation为水平. 绿色:三个LinearLayout,用来实现散列的瀑布流效果.orientation为垂直. 间隙:实际不存在,这里只是为了能看清结构. 布局代码: <com.example.stream.SV android:id="@+id/sv" android:l

分页加载

现在分页加载在apk中应用广泛 那么是怎么实现的呢 下面让我们举一个小例子来看一下 首先是我们的自定义的listview 在布局中引用 那么就看一下我们的布局文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="mat

带表头 固定列可左右上下滑动的可分页加载的ListView

项目描述: 最近做项目,遇到一个问题,就是要求ListView既要有表头,点击表头从能够对特定的列进行排序,并且要求固定第一列,右边的其他列不固定,能够向左滑动的时候,收缩到左侧,向右滑动的时候,显示已经收缩的列,总之就是满足一个需求,一个表里面有很多个列的时候,单个屏幕显示不完所有的列,因此,就做一个可收缩的列表,用于在一个控件里面显示完表中所有的字段. 小的我参考了网上的代码,名字为demoHListView(大家可以到网上搜索下载,或者在我共享的代码中去下载),是用观察者模式来实现的效果,