滚动加载优化

一般情况下,滚动加载是通过在window上绑定scroll事件,实时遍历容器数组,计算每个元素的scrollTop,满足要求的就触发回调,并从数组里删除该节点。

这样的思路最简单,但是我们知道scroll事件的触发是非常频繁的,在每次触发的时候遍历数组,时间复杂度为O(n),需要滚动加载的元素越多,每次滚动过程的遍历就越慢,成线性增长。

在做排行榜的时候,因为全站要进行滚动加载,每次滚动载入的数据量都比较大(每次5k+(gzip)的html,1000个节点左右),所以考虑了一个更优的解法。

我们还是用push的方式添加需要延迟加载的节点,添加的时候进行排序。

Containers.push(lazyContainer);
Containers.sort(function(a, b){
    return D.offset(a).top > D.offset(b).top;
});

再看下面的代码:

var scrollView = function(){
    if(Containers.length === 0) return;

    if(D.offset(Containers[0]).top - D.scrollTop() < 1000) {
        var currentContainer = Containers.shift();
        currentContainer.init();
        scrollView();
    }
};

scrollView();
E.on(window, 'scroll', scrollView);

因为前面添加的时候是事先排过序的,所以滚动过程中,可以只对最小值进行比较,当该值符合滚动展示条件的时候,触发回调然后递归再继续检查数组下一位。

可以看出,这样的复杂度其实只是个常量,O(1)的,尤其是滚动的时候计算元素和scrollTop的偏移值开销也不小,把复杂度降下来之后,每次滚动只会执行一次计算,而不是原来的N次。

可用性降级

KISSY 的 data-lazyload 通过 data-lazyload-src 属性实现内容延迟和图片延迟,但是在手动模式下:

<img data-lazyload-src="http://img01.taobaocdn.com/tps/i1/T1dy8RXjpEXXXXXXXX-225-60.png" />

使得img标签无法降级,无脚本环境里,图片纷纷表示无法显示.

在目前的基础上,考虑加入扩展:

<style>
.js-supported {
    visibility: visible;
}
.js-not-supported {
    visibility: hidden;
}
</style>

<noscript>
<style>
.js-supported {
    visibility: hidden;
}
.js-not-supported {
    visibility: visible;
}
</style>
</noscript>

<img data-lazyload-src="http://img01.taobaocdn.com/tps/i1/T1dy8RXjpEXXXXXXXX-225-60.png" class="js-supported" />
<img src="http://img01.taobaocdn.com/tps/i1/T1dy8RXjpEXXXXXXXX-225-60.png" class="js-not-supported" />

后来讨论过程中@ktmud 老师提到另外一个简洁的实现,采用noscript标签加一点脚本来延迟图片:

<noscript class="KS_Data_Lazyload">
    <img src="http://img01.taobaocdn.com/tps/i1/T1dy8RXjpEXXXXXXXX-225-60.png" />
</noscript>

脚本里,通过读取noscript的内容并插入到文档流里,在kissy里,可以这么搞:

var D = KISSY.DOM;
KISSY.all('noscript.KS_Data_Lazyload').each(function(ns) {
    ns.parent()[0].insertBefore(D.create(D.text(D.create(ns.html()))), ns[0]);
});

无脚本环境里,直接就显示noscript里的内容;有脚本环境里,脚本就把noscript里的东东取出来,按需延迟加载.

而这种方案因为noscriptinnerHTML是一段text,故而所需要的DOM操作比目前的方案要多两次DOM操作,适合在某些重要场合进行应用,比如首页SRPDetail等等.

DEMO: noscript lazyload

 

 

 

ImageLazyLoad技术,就是在下拉滚动条的时候加载图片,这种比较适合一个网页上有很多图片的情况,例如我的网站:www.uucc5.com 满页都是图片,那么如果用户访问的时候,会在加载完整个页面等待很长时间,而用第一眼看到的只是第一屏的内容,所以第二屏、第三屏等的内容加载时间其实是在浪费时间!如果用户只看了第一屏,而不翻屏就关掉了浏览器,那么第二屏第三屏下载的资源也是一中流量的浪费! 并且加载用户体验也不好!那么这就有了这个小技巧,使用javascript来实现图片缓冲,只加载用户要看的屏幕的资源,这个小技巧的好处是提高访问速度,提高用户体验,对seo没有什么帮助!,不废话,说做法:

一、使用JQuery插件 ,插件名: jquery.lazyload(7kb大小),压缩后(3kb大小):

1.导入JS插件
<script src="http://jianzi0307.blog.163.com/blog/jquery.js" type="text/javascript"></script>
<script src="http://jianzi0307.blog.163.com/blog/jquery.lazyload.js" type="text/javascript"></script>
2.在你的页面中加入如下的javascript:
$("img").lazyload();
这将会使所有的图片都延迟加载。

当然插件还有几个配置项可供设置:
1.改变threshold
$(“img”).lazyload({ threshold : 200 });
把阀值设置成200 意思就是当图片没有看到之前先load 200像素。

2.当然了你也可以通过设置占位符图片和自定事件来触发加载图片事件
复制代码
代码如下:

$("img").lazyload({
placeholder : "img/grey.gif",
event : "click"
});

3.可以通过定义effect 参数来定义一些图片显示效果
复制代码
代码如下:

$("img").lazyload({
placeholder : "img/grey.gif",
effect : "fadeIn"
});

LazyLoad(延迟加载)技术不仅仅用在对网页中图片的延迟加载,对数据同样可以,Google Reader和Bing图片搜索就把LazyLoad技术运用的淋漓尽致;

缺陷:
1.与Ajax技术的冲突;
2.图片的延迟加载,遇到高度特别高的图片,会出现停止加载的问题;
3.写代码不规范的同学要注意了,不管由于什么原因,如果您的页面中,img标签的height属性未定义,那么我建议您最好不要使用ImageLazyLoad

二、使用淘宝的延迟加载技术:(2kb大小)
http://a.tbcdn.cn/kissy/1.0.0/build/imglazyload/imglazyload-min.js
调用方法也是很简单的:
<script src="http://jianzi0307.blog.163.com/blog/http://a.tbcdn.cn/kissy/1.0.0/build/imglazyload/imglazyload-min.js" type="text/javascript"></script> <script type="text/javascript">// <![CDATA[KISSY.ImageLazyload();//]]></script>
注:该脚本依赖 yahoo-dom-event, 页面中需要加载 yui 2.x,你也可以直接引用下面的地址:
<script src="http://jianzi0307.blog.163.com/blog/http://kissy.googlecode.com/svn/trunk/third-party/yui2/yahoo-dom-event/yahoo-dom-event.js" type="text/javascript"></script>

配置参数如下:

<script type="text/javascript">
KISSY.ImageLazyload({
mod: "manual", // 延迟模式。默认为 auto
diff: 200 // 当前屏幕下多远处的图片开始延迟加载。默认两屏外的图片才延迟加载
});
</script>

manual 模式时,需要手动将页面中需要延迟加载的图片的 src 属性名更改为 data-lazyload-src. 比如 SRP 页面,宝贝列表的后20个图片延迟加载。 输出时,html 代码为:
<img data-lazy-src="http://jianzi0307.blog.163.com/blog/path/to/img" alt="something" />

如果您是Jquery,Prototype等这些JS框架的粉丝,他们都有定制的LazyLoad Plugin提供:http://www.appelsiini.net/projects/lazyload

LazyLoad(延迟加载)技术不仅仅用在对网页中图片的延迟加载,对数据同样可以。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐