美文网首页HTML5HTML5 Canvas首页投稿(暂停使用,暂停投稿)
解决html5上拉加载数据时的一系列问题---页面卡顿、数据重复

解决html5上拉加载数据时的一系列问题---页面卡顿、数据重复

作者: 跑神的心 | 来源:发表于2017-07-18 11:29 被阅读3477次

    页面很简单,先上效果图

    吐槽

    某日,暴雨,南京的某个角落

    领导: 排面,来一下,我有一个小想法 。

    我:怎么了,海哥,是不是有新功能要做,我等这一天好久了(MMP 就你想法多,听听歌撩撩妹不好吗)。

    领导: 最近用户也突破120万了,项目处在稳定的维护期,所以我想新增加一个小功能 。

    我: 什么功能你说吧,作为高级工程师,公司的颜值担当,没有什么是我解决不了的。

    领导:我想做个一键洗车功能,给用户展示附近的洗车场,然后提供导航。用 h5实现,后期方便更新维护,你来写 h5和 iOS 。

    我:(What?那我的王者荣耀怎么办)恩,您真是有远见,站在用户角度考虑。但我们产品和 UI 刚离职,没有原型和效果图,所以这个想法是不是有点不成熟 。

    领导:只要有梦想,人人都是设计师 。

    我:(ZZ....)

    第二天来公司,我就收到了一副惨无人道的效果图,它大概是这个样子


    我怎么怎么办,我也很绝望啊。

    正文

    前面加载数据的基本操作不做过多描述,直接进入正题。

    判断上拉条件

    此处后台接口除了返回一个头部信息外 + 10条列表数据,此时的参数 pagenum 为1。当上拉到页面底部时,再发一次 ajax 请求,参数 pagenum为2,以此类推。那么,怎么判断页面刚好到了底部。


    假设此时是刚加载完数据的初始状态,可以看到还有一部分数据没有加载出来,处在在屏幕外。当此时手指往上滑动,进入下图这个状态。


    所以当监听页面的 touchmove事件。 所有内容高度 = 屏幕高度 + 滑动高度时 。发送 ajax 请求,加载下一页数据。

    windowH = $(window).height();
    scrollH = $(document).scrollTop();
    documentH = document.documentElement.scrollTop==0? document.body.scrollHeight : document.documentElement.scrollHeight;  
    if (windowH + scrollH >= documentH - 20) {
          console.log("这里页面到达底部");
         //执行 ajax 操作
         $.ajax({
              datatype : "JSON",
              type : "POST",
              url : "jiekou.htm",
              timeout : 15000,
              async:true,
              data : { key:value,pagenum:pagenum},
              error : function (e) {},
              success : function(json) {
                   //for 循环加载数据
                   pagenum = parseInt(pagenum) + 1;
              }
         });
    }  
    

    这里选择的是异步请求,同步请求当用户网络差或者我们服务器速度慢时,会卡死页面,并且需要等到timeout 之后才能进行下一次刷新加载,严重影响用户体验。

    问题关键

    但是此时出现了一个新的问题,当滑动到底部时,上面的输出语句 console.log("这里页面到达底部") 会调用数十次。因为 touchmove 事件一直响应,只要满足我们的判断条件,就会进入方法内执行输出语句。

    因为我们前面选择的异步请求,所以ajax 请求也会执行数十次,就会出现大量的重复数据。解决这个问题有两个办法:

    • 改为同步请求,一次加载未完成不会进行下一次请求。
    • 继续使用异步,新增一个参数进行判断,当前后两次的pagenum不同才进行新的请求。

    第一个方法直接放弃吧,不然会被领导搞死。

    if (windowH + scrollH >= documentH - 20) {
        if (pagenum != lastpangenum) {
         //当此时的pagenum跟上一次不同时,才调用
         lastpangenum = pagenum;//更新lastpangenum
         //执行 ajax 操作  
        }
    } 
    

    这样做得话问题好像已经被解决了。但是当你把 timeout 参数改的非常小,模拟网络差请求超时情况,发现 if (pagenum != lastpangenum) 条件永远不执行。因为没有走 success 方法,pagenum没有+1所以我们需要处理请求失败的情况。在 error 方法里打破 pagenum = lastpangenum 均衡。完整的代码如下:

    if (windowH + scrollH >= documentH - 20) {
      if (pagenum != lastpangenum) {
             lastpangenum = pagenum;//更新lastpangenum
             //执行 ajax 操作
             $.ajax({
              datatype : "JSON",
              type : "POST",
              url : "jiekou.htm",
              timeout : 15000,
              async:true,
              data : { key:value,pagenum:pagenum},
              error : function (e) {
                    lastpangenum = lastpangenum - 1;
              },
              success : function(json) {
                   //for 循环加载数据
                   pagenum = parseInt(pagenum) + 1;
              }
         });
     }
    }  
    

    小Tips

    问题基本上就是这么多,作为一个非专业前端开发,一切还在摸索的过程中。这里放上几个常用的小方法,以备后用。

    1,取当前URL 中的参数
    function getUrlVars() {
        var vars = {};
        var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&#]*)/gi,
              function(m,key,value) {
              vars[key] = value;
               }
         );
        return vars;
    }
    
    //用法(假设 url 为 www.baidu.com?guid=12345&token=kd1247da)
    var guid = getUrlVars()["guid"];
    
    2,获取时间戳,时间戳与正常格式转换
    var nowtimestamp = new Date().getTime();//得到时间戳
    var commentime = getLocalTime(nowtimestamp);//得到普通格式时间
    
    function getLocalTime(ns) {  
            var d = new Date(ns);  
            var dformat = [ d.getFullYear(), d.getMonth() + 1, d.getDate() ].join('-')   
                        + ' ' + [ d.getHours(), d.getMinutes(), d.getSeconds() ].join(':');  
            return dformat;  
    }
    
    3,Android平台与iOS平台判断
    var u = navigator.userAgent;
    var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
    var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
    if(isAndroid ===true){
    }else if(isiOS===true){
    }
    
    4,iOS返回不响应
    <a href="#" onclick="window.history.back();return false;>
    //在后面加return false,屏蔽 a 标签的默认操作
    

    持续更新中...........

    结语

    整个功能做下来持续了一个多星期,也遇到过不少问题,对于 h5的很多底层原理知之甚少,更谈不上优化。最近在看俞甲子那本程序员的自我修养--链接、装载与库 发现自己对于一些底层知识越来越感兴趣,总觉得它像武林里的内功,一通则百通。好吧,扯得有点远了。等等.....领导好像又在叫我了.......

    相关文章

      网友评论

      本文标题:解决html5上拉加载数据时的一系列问题---页面卡顿、数据重复

      本文链接:https://www.haomeiwen.com/subject/ofpckxtx.html