图片的预加载就是在加载大图片前,先显示一个loading.gif,就算在网络比较慢的时候也能让人知道正在加载,总比啥反应都没有强。

下面这段代码就是预加载的一个简单的实现,假设先不处理加载图片时的onError,onAbort,超时的问题。

只关注代码的结构。

复制代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <button id='btnLoadImg'>加载图片</button>
        <br>
        <div id='imgContainer'>
        </div>
        <br>

        <script type='text/javascript' src="./jquery-1.11.3.min.js"></script>
        <script type='text/javascript'>
            $(document).ready(function(){
                $('#btnLoadImg').bind('click', doLoadImg);
            });

            function doLoadImg(){

                var eleImg = createImgElement();
                document.getElementById('imgContainer').appendChild(eleImg);

                loadImg(eleImg, 'http://img.wanchezhijia.com/A/2015/3/20/17/11/de63f77c-f74f-413a-951b-5390101a7d74.jpg');
            }

            //创建img标签
            //这里用自执行函数加一个闭包,是为了可以创建多个id不同的img标签。
            var createImgElement = (function(){
                var index = 0;

                return function() {
                    var eleImg = document.createElement('img');
                    eleImg.setAttribute('width', '200');
                    eleImg.setAttribute('heght', '150');
                    eleImg.setAttribute('id', 'img' + index++);
                    return eleImg;
                };
            })();

            //预加载图片
            //给img标签设一个加载图片,通过Image对象预先加载实际图片加载完成后设到img标签上
            function loadImg(img, src) {
                var imgCache = new Image();
                imgCache.onload = function(){
                    img.src = this.src;
                };

                img.src = 'loading.gif';
                imgCache.src = src;
            }

        </script>
    </body>
</html>
复制代码

 

以下预加载的代码功能上是满足了,但是它的职责包含了预加载和加载两个职责,违反了“单一职责原则”。所谓的职责就是“会发生的变化”,如果网速的 问题不再是问题或者加载的图片的分辨率被控制在很小的时候等,需要去掉预加载的功能,这时候就要修改loadImg的代码,就要重新跑所有相关的测试,即 违反了“开闭原则”,又增加测试工作。

复制代码
            function loadImg(img, src) {
                var imgCache = new Image();
                imgCache.onload = function(){
                    img.src = this.src;
                };

                img.src = 'loading.gif';
                imgCache.src = src;
            }
复制代码

 

加载和预加载其实就是代理模式的一种,代理模式可以理解成,你会开车但是因为某种原因只能找人代理开车,因为不了解MM的喜好找人代理送花。

将预加载功能改成代理模式可以理解成:本体先显示个门面,找代理去加载,加载完了,告诉本体,本体把图片贴上去就行了。

既然如此,本体的职责就很简单了,就往门面上贴。

加载本体函数:

            function loadImg(img, src) {
                img.src = src;
            }

 

做一个预加载代理函数:

复制代码
            function loadImgProxy(img, src){
                var imgCache = new Image();
                imgCache.onload = function(){
                    loadImg(img, this.src);
                };

                loadImg(img, 'loading.gif');
                imgCache.src = src;
            }
复制代码

在代理函数中,先让本体加载loading.gif,等大图加载完了再让本体加载实际图片。

代理还是和本体函数的接口参数是一致的,职责分的比较清晰,如果到时候要把预加载去掉,也不需要修改本体和代理的代码,只需要在调用的地方把代理的名字换成本体的名字即可。

可以适当的把代理函数改一下,可以让其适应加载多个图片的场景,其实就是做一个闭包,把缓存Image对象变成私有即可:

复制代码
            var loadImgProxy = (function(){
                var imgCache = new Image();

                return function(img, src){
                    imgCache.onload = function(){
                        loadImg(img, this.src);
                    };

                    loadImg(img, 'loading.gif');
                    imgCache.src = src;
                };
            })();
复制代码

 

修改后的完整代码:

复制代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <button id='btnLoadImg'>加载图片</button>
        <br>
        <div id='imgContainer'>
        </div>
        <br>

        <script type='text/javascript' src="./jquery-1.11.3.min.js"></script>
        <script type='text/javascript'>
            $(document).ready(function(){
                $('#btnLoadImg').bind('click', doLoadImg);
            });

            function doLoadImg(){

                var eleImg = createImgElement();
                document.getElementById('imgContainer').appendChild(eleImg);

//使用代理函数进行加载
//如果某一天不需要预加载了,就把loadImgProxy换成loadImg即可 loadImgProxy(eleImg, 'http://img.wanchezhijia.com/A/2015/3/20/17/11/de63f77c-f74f-413a-951b-5390101a7d74.jpg'); } //创建img标签 //这里用自执行函数加一个闭包,是为了可以创建多个id不同的img标签。 var createImgElement = (function(){ var index = 0; return function() { var eleImg = document.createElement('img'); eleImg.setAttribute('width', '200'); eleImg.setAttribute('heght', '150'); eleImg.setAttribute('id', 'img' + index++); return eleImg; }; })();
//加载图片本体函数 function loadImg(img, src) { img.src = src; }
//加载图片代理函数 var loadImgProxy = (function(){ var imgCache = new Image(); return function(img, src){ imgCache.onload = function(){ loadImg(img, this.src); }; loadImg(img, 'loading.gif'); imgCache.src = src; }; })(); </script> </body> </html>
复制代码
posted on 2015-11-05 15:57  杨杨0708  阅读(186)  评论(0编辑  收藏  举报