使用 ScrollLoading 替代 LazyLoad 实现真正的延迟加载

作者: iEdon 分类: 早期归档 发布时间: 2015-05-23 14:47

提示:本文参考自 CNBLOGS、鑫空间(我们所使用的插件 ScrollLoading 即由大牛@张鑫旭制作)。

什么是 LazyLoad?

大家的博客或多或少都会有一些图片,当一个页面上图片过多时,网页加载会变慢,而且服务器压力也会增大。所以,一般地,我们使用 jQuery 插件 LazyLoad 来使图片实现延迟加载。但是,iEdon 注意到一些大牛发现 LazyLoad 其实是伪延迟加载,并不能达到真正的效果。

真相:

百度搜索“图片分屏加载”,映入眼帘的就是jquery.lazyload,相信很多人用过,或许现在还在用,今天我就来说说这个插件的严重BUG。

何为图片分屏加载?顾名思义,就是让图片出现在浏览器可视区域内时,才进行加载。好处就是当页面上图片过多时候,不需要一次性加载完,大大提高了友好性,也减轻的服务器的压力。

我们发现,第一屏内的图片,是正常加载了,当滚动到第二张的时候,过了几秒,也渐显出来了,似乎没什么大问题。这时,我们用火狐的firebug再来观看下,当然为了确保测试稳定,我用金山卫士清空了浏览器缓存。

LazyLoad 无效 1

看到了么?说好的分屏加载的效果呢?怎么还是有2个请求。第一屏就一张图片,但实际上已经把两张图片都加载好了。坑爹的还不仅如此,我们继续看,当我把滚动条滑动到第二张图片……

LazyLoad 无效 2

纳尼?第三个请求出现了!!!我一共两张图片,用了jquery.lazyload居然要下载3张,不仅没有减轻服务器压力,反而增加了,这不明摆着坑爹嘛。

之后,我看了下lazyload的源码,其实逻辑上都是OK了,把img的src里的值,存放到自定义的original属性里,当图片滚动到浏览器可视区域内时,再把original里的值赋回到src里,实现分屏加载。

但问题就出在调用上,lazyload的调用方法是写在$().ready(function(){});里,如:

也就是在页面载入完毕后才调用lazyload,而页面载入完毕后,图片也都下载好了,再去使用 LazyLoad 已经没有必要,反而就会出现上面说的那种情况:一共只有2张图片,却向服务器请求了3次,下载了3张图片,适得其反。

网上有篇修改 jquery.lazyload 的文章,大家可以搜搜,不过我试了下,还是不行,直接不加载了。

关于这问题的解决方法,就是换插件,iEdon 找到另一个分屏加载的插件,叫:jquery.scrollLoading。这个插件真正实现了图片分屏加载。

使用 ScrollLoading:

虽然只有几十行代码,但是为了方便使用,我还是将其插件化了。插件名为 jquery.scrollLoading.js,您可以狠狠地点击这里 下载(右键 – [目标|链接]另存为)。使用 ScrollLoading 还有一个好处,它不仅支持图片延迟,也支持资源延迟(诸如 HTML)。

首先确保你的主题使用了 jQuery,移除 LazyLoad 可能因主题不同而造成差异,这里不做阐述。

在你的主题 header.php 或 footer.php 里面加入:

然后在主题JS或者是直接在HTML中嵌入。

注:此插件的方法名就是scrollLoading,所以,用法就是直接:包装器.scrollLoading();就可以实现滚动加载效果了,简单的吧。如下:

表示所有class为scrollLoading的元素绑定了滚动加载的方法。
当然,不可能真的就如此简单,我们还需要做点小动作的。元素默认是不加载的,那么真正的加载地址显然要预先在元素上放置的,例如新浪微博默认把头像地址绑在了一个自定义的”dynamic-src”属性上,见下图:
SinaLazyLoad
在HTML5中,以data-开头的自定义属性都是合法的,且地址可以是图片,页面等。所以,我设定了绑定地址的自定义属性为”data-original”(在 ScrollLoading 中可以修改自定义属性名称),此属性值设为真实的图片(或页面)地址就可以了。例如下面:

会在滚动时加载名为loaded.html的页面,并自动替换里面的内容。
对于常用的图片,还有一点小问题,就是其默认的src图片地址。其src地址不能是真实的图片地址(否则会直接一次性全部加载),也不能是空地址或是坏地址,否则IE浏览器下会出现很惊悚的红叉叉。我的做法是默认链接的是一个1px * 1px的gif透明图片(大小很小),同时可以透出后面加载中gif动画图片,当滚动加载的时候直接把此gif图片替换掉。于是,对于图片,可能就有类似下面的代码:

在 WordPress 中,我们可以修改 functions.php 以及其他调用图片的地方,将属性  src  改为 data-original,并新增一个替代的 src  属性指向延迟加载的 Loading 动画。这里不做阐述,因为这个方法已经烂大街。

附录:ScrollLoading 可选参数

ScrollLoading 是个很简单很小的插件,所以参数也很少,见下表:

参数 默认 释义
attr data-original 获取元素加载地址的属性名
container $(window) 滚动的容器。默认为$(window),也就是默认的网页滚动。
callback $.noop 回调。元素动态加载完毕后执行的回调函数。其中回调函数的上下文this就是当前DOM元素。注意:如果无法获取元素加载地址,则不执行动态加载,但是会触发回调。在某些需求下,您可以缺省url值,仅仅触发回调。

一个完整的使用 DEMO:

最后,能好好利用 ScrollLoading,就会给你的访客、服务器带来巨大的利处。iEdon 推荐大家使用 ScrollLoading。使用效果可以参考 iEdon Inside。

27条评论
  • mooc

    2015年5月23日 下午11:15

    以后弄个玩玩。。(图片亮了)

    1. iEdon

      2015年5月23日 下午11:17

      好基友,不知怎地,越来越爱你啦 😆

  • Taciturn

    2015年5月24日 上午9:52

    可惜基于Node.js的博客系统无法使用。

  • Leniy

    2015年5月25日 下午10:01

    顶上这个动画好高大上

    1. iEdon

      2015年5月25日 下午10:36

      就是普通的CSS动画呀,话说你终于有时间来逛逛了呀。

      1. Leniy

        2015年5月31日 上午9:57

        soga,原来是两个animation,没注意。

        1. iEdon

          2015年5月31日 下午10:52

          用这个发现了ie存在渲染bug,只有一个动画在动。用ie开发人员工具把动画勾勾去掉再勾上就正常了

  • Leniy

    2015年5月25日 下午10:01

    另外,我怎么记得lazyload有个插件,是把所有img的src属性替换掉

    1. iEdon

      2015年5月25日 下午10:38

      我记得是通过主题functions.php中加钩子,给img进行属性替换的。如果是基于js,那么网页还是会全部加载下来。

      1. Leniy

        2015年5月31日 上午9:58

        加hook,然后wctc缓存。

        1. iEdon

          2015年5月31日 下午10:53

          太高级,用不起????

  • 锋子

    2015年5月26日 上午9:17

    图片中的字体挺好看的

    1. iEdon

      2015年5月26日 下午10:37

      我叫不出名字来,不过这些字体经常在一些教辅封面上看到。

  • 平凡之路

    2015年5月27日 上午10:36

    这个有用,记录下来回去玩玩!

    1. iEdon

      2015年5月27日 下午10:29

      哈哈,不过这个还是很折腾的!

  • FROYO

    2015年5月27日 下午11:26

    文章够长的,没耐心看下去了。。。

    1. iEdon

      2015年5月29日 下午9:47

      不长啊,试试你有没有耐心吧META的那篇看完 😛

      1. FROYO

        2015年5月29日 下午11:12

        一样不行啊

      2. iEdon

        2015年5月30日 上午11:21

        你应该去锻炼毅力了 😯

  • WordPress主题

    2015年5月31日 下午6:11

    不错!!

  • 已查水表

    2015年6月1日 下午1:09

    效果不错哦~

  • 豆采

    2015年6月7日 下午7:16

    你好,可以贴出在fun中添加的代码吗?

    1. iEdon

      2015年6月7日 下午10:18

      好的,自动添加 data-original 的代码应该是这样(网上流传的方法有误):

      1. 豆采博客

        2015年6月13日 下午11:28

        十分感谢你的回复。

      2. 豆采博客

        2015年6月14日 上午12:23

        测试了三次还是不能加上class 。。。

        1. iEdon

          2015年6月14日 下午10:30

          有没有安装钩子 (add_action)?如果没有,那么这个函数无法起作用。

  • Timle

    2015年8月13日 下午4:30

    有空试试你的这段代码,我站现在用的lasyload,刚看了以下好像还真有你说的这种情况。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

标签云