八月
27

JS延迟加载机制函数(Lazyload)

最近应该大家都发现了,我的博客很多模块都使用了延迟加载技术。这个延迟加载(lazyload)我第一次听说其实还是不久前,那是在别人博客看到介绍的一个基于jQuery的图片延迟加载插件。我对这个很感兴趣,其实很多网站也都应用了这个技术,尤其是大型网站,可以有效地减少服务器压力。

我原先觉得这个技术挺神秘的,实现起来应该比较困难,并且在网上也并没有找到相关的文章或者介绍。但是当我真正决定要去这样做时,却发现其实这个真的挺简单的,原理也容易理解。

lazyload,简单地说,就是在浏览器滚动到某个位置时再出发相关函数,实现页面元素的加载或者某些动作的执行。浏览器的滚动位置检测,可以通过一个定时器来循环检测,通过比较某一时刻页面目标节点位置和浏览器滚动条高度来判断需不要要执行函数。我将这个方法写成了一个类,我自己博客即是使用我的这个方法。

(下面代码纯属自己的小试手,如果有不完善地方可以指出)

   1: function Lazyload(func, obj) {//obj目标节点对象, func要触发的函数
   2:     this.func = func;
   3:     this.obj = obj;
   4:     this.it = setInterval(function() {//2s检查一次
   5:         this.checkScroll();
   6:     }.bind(this), 2000);//bind为setInterval绑定lazyload对象,否则this会指向window对象
   7: }
   8:  
   9: Function.prototype.bind = function(obj) {//对象绑定
  10:     var __method = this;
  11:     return function() { 
  12:         return __method.apply(obj, arguments); 
  13:     };
  14: }
  15:  
  16: Lazyload.prototype.checkScroll = function() {
  17:     var scrollY = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset || 0,//页面滚动条高度
  18:         seeY = window.innerHeight||document.documentElement.clientHeight,//浏览器可视区域高度
  19:         func = this.func;
  20:     if (Math.abs(this.getY() - scrollY) < seeY) {//当目标节点进入可视区域,即页面滚动条高度减去节点距页面顶部距离小于浏览器可视高度
  21:         clearInterval(this.it);//清除定时器
  22:         return func();
  23:     }
  24: }
  25:  
  26: Lazyload.prototype.getY=function(){//目标节点距页面顶部高度
  27:     var obj=this.obj;
  28:     tp = obj.offsetTop;
  29:     if (obj.offsetParent) while (obj = obj.offsetParent) tp += obj.offsetTop;
  30:     return tp;
  31: }

关于代码的一些解释都在注释里了。如何使用呢?

使用这个方法要通过new来新建类对象的方法。参数func即是要触发的函数,obj即是页面上某个节点对象,即当此obj节点进入可视区域时(浏览器滚动到此处)即触发func函数。比如,你要实现当浏览器滚动到页面上id为“test”的节点(b)时触发弹出窗口alert(‘yes’),可以这么做

   1: function a(){alert('yes');}//要出发的函数
   2: var b=document.getElementById('tests');//获取页面节点
   3: new Lazyload(a,b);//使用new关键字建立对象执行

以上就是我自己的lazyload的全部代码与实现方式了。当然,我相信它还有改进之处。

补充一些其他的东西:

我的代码中定时检测的时间设定是2s,也就是说每两秒去比较一次。如果你浏览器拖动太快,目标节点被很快的一闪而过,很可能此时就刚好没有执行checkScroll函数,所以也就不会触发动作了。你可以将时间改为更小的值(在第6行),如500ms,可以避免大多数的快速拖动造成的问题。当然,我觉得其实没必要,如果某人很快的拖动滚动条,说明他要浏览的东西在页面底部,那么其实是没必要加载他快速拖动过的节点的,所以2s我觉得是一个很合理的值。

另外一个问题是我的代码是只触发出现在可视区域中的节点动作,如果你想要实现在当前浏览的页面以上部分的节点全部要加载,那么可以将代码的第20行去掉Math.abs即可。如果要实现在滚动到距目标节点一定高度时就开始触发函数,那么可将20行的seeY改为seeY+200(200即为设定的距离高度)。

关于lazyload的一个具体的实现,就还拿图片的延迟加载来说吧。你可以将图片的地址都改成一个默认的小图片(这个可以在后台用php直接修改输出,也可以用js实现),将正真的图片地址存到图片的alt属性中(也可以指定一个自定义的属性),然后对每个图片绑定new lazyload,要触发的动作函数就是将alt中的值赋给src即可。这样,就实现了图片的lazyload(你就可以消灭jQuery,消灭jQuery的lazyload插件了,也就消灭了那100来K的JS文件)。如果再结合ajax技术,那么也就可以实现如我博客一样的模块延迟加载了。捕获

本文标签: , , , ,

分享

本文短网址: http://qiqi.boy.im/7s

这篇文章已经有 98 条评论

Comments (98) Trackbacks (0)
You can leave a response or Trackback this entry .
  1. 小闇 -#1

    看看

  2. 柳城 -#2

    JQ看几时开始学学

  3. QiQiBoY -#3

    小闇 :@QiQiBoY
    一直開著tween就看到你和木木的新文,蛋定強搶SF去~

    。。。。。 :twisted:

    @小闇
    昨天你的大喊“SF”真是让我乐了半天。。。 :grin:

    • 小闇 --#1

      @QiQiBoY
      啊啊啊啊啊啊啊啊啊啊啊啊啊不要再提那件事不要再提那件事不要再提那件事不要再提那件事不要再提那件事不要再提那件事我羞死了我羞死了我羞死了我羞死了(←瘋癲中

    • QiQiBoY --#2

      @小闇
      :grin: 好的,我不提了。。但是我相信会有好奇的同学去围观的。。 :grin:

    • winy --#3

      @小闇
      围观+1

    • 小闇 --#4

      @winy
      啊啊啊啊啊啊啊啊啊啊你滾-------- :twisted: :twisted: :twisted: (←方寸大亂中

  4. zwwooooo -#4

    一句都看不懂……js……我还是玩玩jQ的皮毛吧

    • QiQiBoY --#1

      @zwwooooo
      我当初看到带有this、prototype这些关键字的js代码时也会感到很晕。。慢慢的就知道怎么一回事了。。

  5. ak477777 -#5

    嗯,惰性加载,按需获取,其实这种思想在软件工程方面随处可见,也相当重要

  6. Bee君 -#6

    代码在这里,但是实战起来~~我还是觉得十分困难

  7. snowxh -#7

    昨天刚在一个台湾淫的blog里看过类似的~

  8. Max Lee -#8

    以后试试用在我的博客上!

  9. ZH CEXO -#9

    说实在的我还看不懂,不过看上去挺有意思的,我慢慢理解好了
    另外给你找个小bug,你的留言框用鼠标点击的话,会出现富文本编辑器,但是用tab键从website处切过来的时候编辑器就不会自己载入,你解决解决 :razz:

  10. hzlzh -#10

    我曾加上 并推广,现在去掉了,嘿嘿 懒~

  11. 掌柜的马甲 -#11

    网站网速不好,用lazyload会看到一大堆加载图,很郁闷的….

  12. Dianso -#12

    评论这里的ajax刷新好慢啊,很久才加载出来

    • QiQiBoY --#1

      @Dianso
      呵呵,因为循环检测时间是2s。。。运气不太好的话要先等上2s请求才会发送出去。。。 :???:

  13. Alan -#13

    现在学习也遇到瓶颈,刚开始看的 js,皮毛;然后转战看 jQuery,现在也遇到困难,因为 js 基础不扎实,所以又返回去学 js,唉,头大,烦人。

    • QiQiBoY --#1

      @Alan
      关于js的书本、网上教程太多,但很多讲的不是古老的东西就是在嚼皮毛,看了根本没什么帮助,反而容易被误导。
      推荐你看一本书《JavaScript高级程序设计》作者是扎卡斯。这本书非常好,对学习js很有帮助。

    • Alan --#2

      @QiQiBoY
      其实我想看《JavaScript DOM高级程序设计》,网上好多都没货,晕死。先买《JavaScript高级程序设计》来看吧,第二版刚出不久呢。不懂再请教你。

    • QiQiBoY --#3

      @Alan
      你说的这本书我还没看过。。明天到公司找找看,估计能找到。。
      我周围都是JS高手,你问我的我要不会可以再去请教高手。。。。 :grin:

  14. ❤•终于° -#14

    这么帅…技术文只好来灌水了。

    评论框是用了什么插件吗?

  15. winy -#15

    这个我来折腾下,看看用在评论上不错

    • QiQiBoY --#1

      @winy
      你可以用到你的首页more加载上。。滚到底部的时候就自动加载。。。 :smile:

  16. 静夜燃香 -#16

    lazyload……我真是不明白,我究竟加错到哪儿了,没成功过,最基本最简单直接拿来用的都不行……
    T T

  17. 羽中 -#17

    一直坚持不加这个特效,我的博客图也不少,但是感觉加了这个反而会让访客体验觉得很拖

    • QiQiBoY --#1

      @羽中
      你一定是被那些将lazyload图片加载用到gravatar头像上的人给误导了,对于有很多大图这个lazyload插件还是非常好的,但是对于很小的头像,也使用这个就会使浏览器很卡。。。因为图片太集中,一瞬间需要处理的图片太多。。。。

  18. mice -#18

    看完评论 看完文章..飘过了..
    我那里原来就傻傻的 把头像也给lazyload了.头像一多..我的浏览器 直接假死了…现在改了…

  19. 宁波SEO -#19

    文章比较有技术含量,学习了

  20. Page -#20

    嗯 这种技术特别是对于大量图片 交互界面相当舒服

  1. No trackbacks yet.

Leave a Reply

Hi , say something.

  • :?:
  • :razz:
  • :sad:
  • :evil:
  • :!:
  • :smile:
  • :oops:
  • :grin:
  • :eek:
  • :shock:
  • :???:
  • :cool:
  • :lol:
  • :mad:
  • :twisted:
  • :roll:
  • :wink:
  • :idea:
  • :arrow:
  • :neutral:
  • :cry:
  • :mrgreen: