无限滚动的优化方案(一):预加载实现

最近看了很多关于无限滚动的文章,也在面试中被问到了,优化方案很多,本次针对其中一条优化方案做了一个实际的优化:预加载。

实例简介

之前一直对单页应用有兴趣,所以自己写了一个前端路由,相关的文章见这里,这个单页应用采取hash的方式实现路由。最终的实例页面见这里。仓库在这里是一个经典的单页应用。要做优化的就是主页的信息滚动。这些信息通过ajax从服务器端获取,这里为了方便,服务器端会一直返回数据,哪怕是重复的。
页面如下:

Paste_Image.png

预加载原理

正常情况下我的一个ajax请求服务器端会返回最多10条信息,当用户滑动到页面底部,就会触发ajax请求,发送一条新的请求来获取信息。但是这样造成了用户的等待,但是如果用户空闲,就进行ajax的发送也是不行的,这个浪费了用户的流量。
需要采用一种检测手段,检测用户会不会继续往下看,如果会,就进行预加载,不必等到用户翻到最底部。这样可以最大程度的优化用户的体验

预加载实现

剩余内容的高度检测

理解了原理,其实预加载的核心,就是进行一个即将滚动到底部的一个检测。这里需要用到一些高度,我采用的是

  1. document.body.scrollTop:这个高度是指浏览器滚动的高度
  2. document.body.clientHeight:这个是用户视窗的高度
  3. document.body.offsetHeight:这个是body的高度,也就是整个文档的实际高度。
    这三个高度,前两个加起来就是用户已经翻看的高度,通过与整个文档的高度的对比就能检测到剩余文档的高度,只要这个高度小于阈值(OFFSET),就进行ajax请求的发送,从而实现预加载
var body = document.body;
var height = body.offsetHeight-(body.scrollTop+body.clientHeight);
if(height<OFFSET){
    //浏览器快滚动到底部了
}

scroll事件反复执行带来的性能问题

上述函数可以直接和scroll事件进行绑定,但是这样直接绑定会造成一些不好的影响:

  1. scroll的反复执行降低了页面的流畅度
  2. 当达到目标高度之后,每一次的滚动都符合预加载的要求,所以轻微滚动都会触发n次的预加载请求。

scroll事件优化方案

针对上述第一个问题,可以采用函数节流的方式进行优化,但是要注意,最后一次用户的滚动必须执行,因为有可能最后一次滚动进入了阈值,此时必须尽快执行预加载请求。关于节流的原理网上描述的比较多,此处给一个我实现的包装代码:

method.throttling2 = function(func,delay){
  var inthrott = false;//节流
  var timer;//保证最后一次执行
  return function(){
    var self = this;
    var args = arguments;//保留上下文
    if(!inthrott){//判断上一次是否执行完毕
      func.apply(self,args);
      inthrott = true;
      setTimeout(function(){
        inthrott = false;
      },delay);
    }else {
      clearTimeout(timer);
      timer = setTimeout(function(){
        func.apply(self,args);
        inthrott = false;
      },500);//此处500可以进行加快,主要是希望能够尽快的执行最后一次
    }
  }
}

而要解决第二个问题,就必须要保证上一次ajax请求没有结束之前,不会进行下一次ajax请求。这个其实通过一个标识符就可以解决,默认情况下是true,当ajax请求发送开始,修改为false,此时高度的改变会触发scroll函数,但是函数内部会判断这个标识符,如果为false,就不会进行高度的检测以及下一个ajax请求的发送。而当ajax请求结束后,标志位回归true,从而用户的滚动就可以触发下次的预加载了。

最后的代码大概像这样:

//method是我定义的一些公共方法
method.addevent(window,'scroll',method.throttling2(scrollTop,1000))//绑定scroll函数,通过之前的节流函数对原函数进行包装

//高度检测函数,通过节流之后绑定在了scroll事件上
function scrollTop(){
  var height1 = document.body.scrollTop+document.body.clientHeight;
  var height2 = document.body.offsetHeight;
  if(state){//检测标识变量
      if(height2 - height1 < eleheight*3){
        console.log('到达预加载阈值,开始预加载');
        getInfo();
      }
  }
}
//包装ajax请求,加上标识变量
function getInfo(){
  //从服务器端获取商家发布的新信息
  state = false;
  //发送实际的ajax请求
    {state = true;}//此语句写入ajax的回调
}

总结

目前我在预加载的时候会进行一个输出,方便我的观察以及调试。最后大概用户距离底部300px左右的时候,会触发预加载,此时,用户的任何滚动先经过节流,然后再进行标识的检测,不会出现两次预加载同时出现的情况。达到了我预期的目标。

展望

我认为,现实中还有可能出现一种极端情况:就是用户不断的下滑,在查找之前的一条历史消息,此时,因为我的预加载的阻拦,其实在一定程度上限制了用户的滑动(每次只能同时进行一个ajax请求),这里应该有优化的空间,可以通过检测是否出现在可视区域来进行加载。
另外一个可以优化的点在于图片,如果我的作品里面不是框,而是图片,预加载的效果就不太好,需要图片的懒加载,也就是用户可视范围内才进行图片的加载。还有待后续进行改进

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容