图片的预加载就是在加载大图片前,先显示一个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>

javascript设计模式实践之代理模式--图片预加载的更多相关文章

  1. javascript设计模式学习之六——代理模式

    一.代理模式定义 代理模式的关键是:当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问.代理模式需要和本体对外提供相同的接口,对用户来说是透明的.代理模式的种类有 ...

  2. Javascript图片预加载详解

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  3. 利用CSS、JavaScript及Ajax实现图片预加载的三大方法

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  4. 利用CSS、JavaScript及Ajax实现图片预加载的三大方法(转)

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  5. Javascript图片预加载详解 分类: JavaScript HTML+CSS 2015-05-29 11:01 768人阅读 评论(0) 收藏

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  6. 利用CSS、JavaScript及Ajax实现图片预加载的三大方法及优缺点分析

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  7. Javascript兑现图片预加载【回调函数,多张图片】 (转载)

    Javascript实现图片预加载[回调函数,多张图片] 使用JS实现一组图片动画效果或者使用HTML5 Canvas渲染一系列图片等案例中,需要图片全部加载完成方可运行动画效果.此时程序中就会涉及多 ...

  8. 再谈javascript图片预加载技术

    图片预加载技术的典型应用: 如lightbox方式展现照片,无疑需要提前获得大图的尺寸,这样才能居中定位,由于javascript无法获取img文件头数据,必须等待其加载完毕后才能获取真实的大小然后展 ...

  9. javascript 图片预加载

    <!DOCTYPE > <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta ...

随机推荐

  1. JavaScript很牛

    几年前,我从来没有想过现在的JavaScript竟然会变得几乎无处不在.下面是几个要关注JavaScript的原因. 首先,我认为JavaScript能够得到普及的主要原因之一是,JavaScript ...

  2. Mac配置Qt环境——Could not resolve SDK path for 'macosx10.8'

    前言:解决在Mac端安装Qt后,出现的Could not resolve SDK path for 'macosx10.8'的配置信息. 首先,发现问题之前,先搜索一下.但是搜索的结果都是说,找到配置 ...

  3. IOS 公共类-数字处理

    1.写一个方法,调用的时候交换两个数的值 -(void) swap:(int*)a andNumber:(int*)b{ int temp = *a; *a = *b; *b = temp; } 调用 ...

  4. IOS Animation-KeyPath值

    IOS Animation-KeyPath值 keyPath值 说明 值类型 position 移动位置 CGPoint opacity 透明度 0-1 bounds 变大与位置 CGRect bou ...

  5. Node.js~sails.js~package.json的作用

    回到目录 我们在sails框架进行node.js开发时,会涉及到项目的迁移,当迁移后可能你的module即丢失,这时,希望快速的安装所有的包包,可以使用下面命令 1 cd 你当前的sails项目 2 ...

  6. rabbitmq消息队列——"发布订阅"

    三."发布订阅" 上一节的练习中我们创建了一个工作队列.队列中的每条消息都会被发送至一个工作进程.这节,我们将做些完全不同的事情--我们将发送单个消息发送至多个消费者.这种模式就是 ...

  7. fir.im Weekly - 如何打造真正的工程师文化

    好的工程师,无法忍受低效且无趣的工作.优秀的技术团队应该自上而下的地推进技术平台化建设.DevOps.自动化构建.测试和部署流程,积极采用合适的第三方工具或创造工具,进行周期性的前沿技术分享等等. 先 ...

  8. 谷毅(WingKu)横空出世

    天空划出一道彩虹,谷毅(WingKu)横空出世,这里的产品全由本人开发制作,如有雷同不胜荣幸,欢迎前往下载使用,如果有啥建议或者使用当中遇到什么问题,也可在此留言评论~OK,开张啦~!以后每个产品会以 ...

  9. 用Chrome插件对自动化测试TestWriter进行录制

    1.打开Chrome浏览器,在浏览地址中输入: chrome://extensions/,并勾选开发者模式.如图: 2.点击按钮[加载已解压的扩展程序-].如图: 3.选择Testwriter客户端下 ...

  10. apache2添加模块和添加站点

    apache2添加模块和添加站点 linux下的apache2的目录和windows上的区别还是很大的,但是用起来却更方便了,详解请看另一篇文章http://www.cnblogs.com/wancy ...