做有态度的前端团队

网易FEG前端团队

图册组件优化之路(一)

根据六马系统需要,写了一个图册组件,方便给编辑器添加图册显示使用。

效果可以参考这里:http://game.163.com/2016/chinajoy/2016/07/29/22769_632281.html

匆忙发布了第一个版本出去,发现编辑们流行图册都发一两百张图上去的,由于没有做加载优化,导致问题很明显,一开始需要请求双倍的图片总数请求,页面存在多个图册,打开就会加载得很慢才出来,好多菊花满屏转

一、代码按需加载

图册兼容PC和移动两个web端,一般情况下,都是代码写一块,根据参数或者终端类型判断,来运行对应的代码

这样方式存在以下问题:

  1. 一个页面基本是不会存在同时加载PC和移动端两种图册
  2. 调用一端图册,需要把另外一端的CSS、JS、模板都加载了
  3. 双端的代码会存在比较多的耦合性

按需要加载文件的方式(以下是简易代码)

    //pc.js
    var PC = function(param){}  
    //m.js
    var M = function(param){}
    //main.js
    var Main = function(param){
        //判断当前是移动端还是PC端
        var isMoible = /android|ios|iphone/i.test(navigator.userAgent);
        //加载对应的文件
        if(isMoible){
            //假设已经实现了加载文件的方法load,加载成功后就调用M
            load("m.js",function(){M(param)});
        }
        else{
            load("pc.js",function(){PC(param)});
        }
    }

加载css和模板,跟上面的类似,一并进行加载,不过使用这种方式会存在以下问题(需要自行权衡来使用):

  1. 会需要写多一个入口文件,去按需加载文件,比如上面的:main.js
  2. 由于是异步加载pc.jsm.js,所以不方便由main.js提供接口出来给外部使用
  3. 代码量不多的时候,不推荐这么使用,反而更麻烦了

二、图片按需加载

图册多则能上两百张以上,大图小图一起加载,则会变成双倍图片一起请求,加载量可想而知会很多,大量请求堵塞,使得图册加载很慢,所以图片按需加载显得非常重要,一般我们会比较常用lazyload这个插件来完成,不过其实没必要,自己也能简易实现

1、滚动按需加载

监听滚动条的滚动事件,判断所有图片的位置是否在可视区域内,如果是,则加载此图片出来

    //延时计时器ID
    var scrollTimeId = 0;
    //相册容器
    var testDom = document.getElementById("test");
    //绑定滚动事件
    testDom.onscroll = function(){
        //每一次滚动都清空上一次的计时器事件,避免用户快速滚动不断调用问题
        clearTimeout(scrollTimeId);
        //延迟200ms执行事件,基本为用户滚动停止后才会触发
        scrollTimeId = setTimeout(function(){
            //获取所有的图片
            var imgList = testDom.getElementsByTagName("img");
            //获取容器的滚动位置(相册为左右滚动,所有获取Left)
            var scrollLeft = testDom.scrollLeft;
            var scrollRight = testDom.offsetWidth + scrollLeft;
            //遍历图片列表
            for(var i=0,l=imgList.length;i<l;i++){
                var img = imgList[i];
                var imgLeft = img.offsetLeft;
                var imgRight = img.offsetWidth + imgLeft;
                //判断图片是否在当前滚动的可视区域内
                if((imgLeft >= scrollLeft && imgLeft <= scrollRight) || (imgRight > scrollLeft && imgRight < scrollRight)){
                    //加载图片,一般真实地址在data-src属性中
                    img.src = img.getAttribute("dat-src");
                }
            }           
        },200);
    }

2、点击切换按需加载

图册的大图为用户点击按钮进行切换,最省流量方式为,用户点击哪张我才加载哪张,但这样用户会每次切换都出现加载中的提示,比较不友好,所以改进一下方式,帮用户预加载前后各两张图,减少出现加载提示的几率

    function loadImg(index){
        //假设图册有10张图
        var max = 10;
        //保存要加载的图的索引列表
        var load = [];
        //图片列表
        var imgList = document.getElementsByTagName("img")
        //默认添加当前位置的图片
        load.push(index);
        //判断前后两张图的位置是否合法,合法则添加进去
        if(index - 1 > 0)load.push(index-1);
        if(index - 2 > 0)load.push(index-1);
        if(index + 1 < max)load.push(index+1);
        if(index + 2 < max)load.push(index+2);
        //遍历索引列表,设置图片加载
        for(var i=0;i<load.length;i++){
            img[index].src = img[index].getAttribute("dats-src");
        }
    }

PS:还有性能和内存优化这块没做,下一步会去优化这块的事情

手机阅读请扫描下方二维码: