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

    day7 项目进展 又是一个周三,有轮到我写东西了.首先我们对昨天的成果调试了几遍,改了几个小Bug之后就没有什么问题了,完善了登录界面的代码,学生管理这部分终于被敲定下来,并且正式完工了.然后还生下 ...

  2. 作业二--注册GitHub的过程

    第一步:打开GitHub官网https://github.com/,在界面中输入账号名称.邮箱.密码,然后点击注册按钮. 第二步:注册完成后,选择Free免费账号完成初始设置. 第三步:验证邮箱,打开 ...

  3. Angular实现递归指令 - Tree View

    在层次数据结构展示中,树是一种极其常见的展现方式.比如系统中目录结构.企业组织结构.电子商务产品分类都是常见的树形结构数据. 这里我们采用Angular的方式来实现这类常见的tree view结构. ...

  4. 使用ruby过程中遇到安装gem失败的一些通用解决方案

    ruby语言升级还是比较勤快的.但是数量众多的版本使得程序库的兼容性成了大问题.有些gem表示明确不支持某个特定版本以前的ruby,而有些gem则与较高的版本不兼容.再加上gem本身也有版本,简直是乱 ...

  5. Qt类继承图

    对于学习Qt的,有一个Qt所有类的继承图表,是很有需要的.以下提供了Qt5.1的所有类的继承关系图.看的时候,可以放大和缩小.如需文档下载,可以加入最后的QQ学习群.

  6. IOS Socket 04-利用框架CocoaAsyncSocket实现客户端/服务器端

    这篇文章,我们介绍CocoaAsyncSocket框架的使用,主要介绍实现客户端/服务器端代码,相信在网上已经很多这样的文章了,这里做一下自己的总结.这里介绍使用GCD方式 一.客户端 1.下载地址 ...

  7. JavaScript高级-定义函数(类)方法

    1.定义普通函数(常用) //1.普通函数 function defineFun1(p1, p2) { return p1 + p2; } 2.定义匿名函数(最常用) //2.匿名函数 var def ...

  8. Java对象序列化---转载

    1.概念 序列化:把Java对象转换为字节序列的过程. 反序列化:把字节序列恢复为Java对象的过程. 2.用途 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个 ...

  9. 大叔也说Xamarin~Android篇~监听返回键,单击返回某个webView,双击退出

    回到目录 这个操作在原生android里是很容易实现的,在xamarin里也不难,在activity里有方法OnKeyDown,我们只需要重写一下就可以了,然后通过webView重新加载到要返回的页面 ...

  10. 1.1.1. Atitit Cocos2d-JS v3.x的问题

    1.1.1. Atitit Cocos2d-JS v3.x的问题   1.1. Api 兼容性 场景切换的api都不兼容了...  删除了比较多的api...可以dep啊.. 1.2. gui布局,, ...