javascript预加载图片、css、js的方法示例介绍

预加载的好处可以让网页更快的呈现给用户,缺点就是可能会增加无用的请求(但图片、css、js这些静态文件可以被缓存),如果用户访问的页面里面的css、js、图片被预加载了,用户打开页面的速度会快很多,提升用户体验。在用到一些大图片展示的时候,预加载大图是很不错的方法,图片更快的被呈现给用户。不多说了,作为一个前端攻城师都懂的,下面分享我做的测试和得到的结果。

先说需要知道的服务器返回的status code:
status-code: 200 - 客户端请求成功
status-code: 304 - 文件已经在浏览器缓存中,服务器告诉客户端,原来缓冲的文档还可以继续使用。
本文测试判断文件被是否被缓存,用的就是判断是否返回304.

下面针对预加载的几个方法,在不同的浏览器下加载img/js/css做个测试,主要包括new Image()、object、iframe。以下加载测试的js、css、图片文件,是从几个门户网站找的(为啥找几个?是为了尽可能滴测试到特殊的情况,测试中还真遇到了)。
1、测试用new Image()预加载
1.1、new Image()加载


代码如下:

new Image().src = 'http://img02.taobaocdn.com/tps/i2/T1iQhUXnxpXXXXXXXX-171-48.png'; //淘宝
    new Image().src = 'http://static.paipaiimg.com/module/logo/logo_2011_02_22.png'; //拍拍
    new Image().src = 'http://co.youa.baidu.com/picture/services/images/logo.png'; //有啊
    new Image().src = 'http://img1.t.sinajs.cn/t35/style/images/common/header/logoNew_nocache.png'; //新浪*/

然后再把图片添加到页面内:<img src="xxx" />

加载图片没啥好说的,IE6-9/CM/FF/OP/都返回304,预加载成功。
1.2、测试用new Image()加载css


代码如下:

new Image().src = 'http://a.tbcdn.cn/p/global/1.0/global-min.css'; //淘宝(1)
    new Image().src = 'http://static.paipaiimg.com/member/activate.css'; //拍拍(2)
    new Image().src = 'http://co.youa.baidu.com/picture/services/base.css'; //有啊(3)
    new Image().src = 'http://img1.t.sinajs.cn/t35/skin/skin_008/skin.css'; //新浪(4)
    // http://auto.sina.com.cn/css/newstyles.css
    // 可以用这个测试IE下Expires设置的时间小于当前时间的情况

再把css添加到页面内

这个有区别了:
CM/OP,都返回304(无论有没有设置Expires)。
FF, 全部返回了200。
IE,1/2/4都返回304,而3返回200。对比返回的HTTP-Header可以发现:1/2/4都设置了Expires过期时间,而3没有设置。
说明IE下缓存需要设置Expires(并且设置的时间要大于当前时间),而FF不支持利用new Image()预加载。
1.3、测试用new Image()加载js


代码如下:

new Image().src = 'http://a.tbcdn.cn/s/kissy/1.1.6/kissy-min.js'; //淘宝(1)
    new Image().src = 'http://static.paipaiimg.com/js/pp.noticeBoard.js'; //拍拍(2)
    new Image().src = 'http://co.youa.baidu.com/picture/services/cms_core.js'; //有啊(3)
    new Image().src = 'http://js.t.sinajs.cn/t35/miniblog/static/js/top.js'; //新浪(4)
    new Image().src = 'http://shop.qq.com/act/static/week/fri/bang/day_1_p_0_10.js'; //QQ(5)

再把js添加到页面内。

CM/OP,都返回304
FF,只有5返回了304,也只有5的HTTP-Header最简单(包括:Date、Server、Expires、Cache-Control)。
另外几个的响应头信息内容都比较多,但也都设置了5里面的这几个。找规律,发现另外几个的响应头都有:Content-Type:text/javascript,而5里面没这个。
IE,2/5返回了304,1/3/4返回200,对比响应头,应该还是Content-Type影响的,IE里面2/5都没看到Content-Type。
另外,感谢AndrewZhang(http://www.cnblogs.com/AndyWithPassion/)提到,IE下 image 预加载js在httpwatch下查看content,资源的加载并不是完整的。我这里测试也是如此。貌似有字节限制,测试中2返回的是完整的,5有一部分内容丢失了。所以用new Image加载JS一点都不可取。

这里总结下:预加载图片用new Image()兼容性没问题。但是css/js只有OP/CM可以,IE/FF基本是无效(这点IE/FF到挺有默契)。
2、测试用object预加载

var doc = document,
            obj = doc.createElement('object');
            //obj.data = '123.js'; //Ps: 这样写OP下无效(会把data的内容作为object标签里的text node)
            //obj.setAttribute('data', '123.js'); // img、css、js
            obj.style.cssText = 'position:absolute;top:-1px;width:1px;height:1px;';
            // obj.style.width = obj.style.height = 0;
            doc.body.appendChild(obj); // 插入object 标签需要插入到非head部分,以触发加载*/
            //obj.onload = function(){ alert('loaded') }; // FF/OP/Webkit支持(如果data是图片,IE9也可以)

然后再吧object里面data加载的文件,创建标签加到HTML内测试。

测试结果:
FF/OP/CM: 无论是img/js/css,都返回304。
IE6-8:用object加载img/js/css,会直接Aborted。
IE9比较特殊:
IE9加载js/css,先请求并返回HTTP200,再请求并Aborted,这里实际上是请求1次(第2次Aborted了)。
IE9加载img的情况,先请求并返回HTTP200,再请求返回图片,所以图片需要请求2次。

IE9的第1次请求返回的内容是空的(并且此时浏览器一般会卡住,或者直接失去响应)。 IE9首先会请求url,获取文件类型,判断是JS/CSS就Aborted,判断是图片才加载。

至于IE9第1次请求,大概是靠读取HTTP头信息来得到文件类型,或者偷偷把文件下载下来,然后在沙盒里面测试文件类型。
一个有意思的事情,比如用object加载JS,IE9有时也能加载进来,也就是第1个请求没判断出文件是JS(想看到这个要看运气了,貌似网速慢的时候可能发生)

据说以前IE是靠文件后缀来判断文件类型的,后期用HTTP头信息来判断,而他们都可以伪造,所以object在IE下存在安全问题。
IE6/7,如果文件后缀后缀为.js/.css不会发出请求,如果改成http://xxx/test.js?123.png,就发送请求了,然后用script标签引入,发现可被缓存(css这样搞也OK^^)。
IE8,后缀为js/css也不会发出请求,改后缀为png可以发出请求并得到内容,然后页面创建标签引入,文件并没有被缓存。但如果文件是真正的图片就被缓存了。
题外话:通过上面可以发现,随着IE的升级,安全性也越来越高了。

So,这里的结论是:FF/OP/CM下可以用object预加载,IE就千万别用了。
3、测试用iframe预加载

先创建页面a.html,然后加上下面的js。


代码如下:

var doc = document,
            ifm = doc.createElement("iframe");
            //ifm.id="preLoadIfm";
            // ifm.style.border = ifm.width = ifm.height = 0;
            ifm.style.cssText = 'position:absolute;top:-10px;border:0;width:1px;height:1px;';
            ifm.scrolling = "no";
            doc.body.appendChild(ifm);
    window.onload = function(){ // 预加载当然最好是window.onload之后触发
            //要触发onload,需要先appendChild,然后再写onload(如果顺序颠倒,IE下不能触发)
            // ifm.onload = function(){ alert('ifm loaded'); }
            // contentWindow.document-所有都支持,contentDocument-IE9/FF/OP/CM支持
            var ifmDoc = ifm.contentDocument || ifm.contentWindow.document;
            ifmDoc.open();
            ifmDoc.write('<!doctype><html><head></head><body>');
            //ifmDoc.write('<style>html{background:#000;color:#fff}</style>'); // 用于测试
            //ifmDoc.write('<script>alert("a")<\/script>'); // 用于测试
            //ifmDoc.write('<p>test</p><p>test</p><p>test</p><p>test</p><p>test</p>');// 用于测试
            // 开始加载
            ifmDoc.write('<link rel="stylesheet" href="http://localhost/123.css?2011" />');
            ifmDoc.write('<script defer src="http://localhost/123.js?2011"><\/script>'); //不加defer,你会发现IE卡死。。
            ifmDoc.write('<img width="1" height="1" src="http://localhost/123.png?2011" />');
            ifmDoc.write('</body></html>');
            ifmDoc.close();
    };

然后创建新页面b.html,把要上面预加载的文件加到html里面,测试是否已经预加载。
结果:IE/FF/OP/CM都成功预加载。

需要说明的是:当打开a.html后,再刷新页面后,iframe内加载文件的情况。
FF,返回200(注意,这个200不是服务器返回的200,是请求缓存成功。因为发送请求的时间显示的是0)。
CM,显示状态是(from cache).
OP,虽然显示状态是n/a,但是也是from cache。 IE,IE自带的调试工具显示304,HttpWatch显示from cache。

测试环境:
WIN7 EN SP1:OP 11.50、IE7-9、FF 3.6/6.0、Chrome 10
XP EN SP3:IE6
XP EN SP3:IE7
XP CN SP3:IE8
工具:IE9自带的调试工具、HttpWatch、firebug、chrome自带的调试工具、Opera Dragonfly。

最后得出的结论:js预加载图片使用new Image()基本够用了。但是css、js特殊一些,使用object需要判断浏览器。如果考虑到js、css、img都能兼容实现预加载,可以考虑使用iframe。

另外,上面的方法创建iframe后,不使用write()写入要加载的文件,直接设置iframe.src = "cache.html",然后把要预加载的文件写在cache.html内也是可行的(以前看过有文章介绍新浪微博是这样做的,但是文章地址找不到了,搜索也没搜到),cache的网址我收藏了:http://tjs.sjs.sinajs.cn/miniblog2/static/html/cache.html,但是看微博的首页没找到这个,不知道在哪个页使用的。
其他预加载的一点补充

doc.createElement('script') 可以预加载js,如果js里面有对页面的操作,就会对页面产生影响。
doc.createElement('link') 可以预加载css,但是对当前页面的样式也可能会有影响。
所以这样预加载不太可取。
用ajax加载img/js/css,兼容性不错,文件可以被缓存,但是只能限制同域,所以使用范围有限。
预加载图片还可以利用CSS的背景图片实现。牛人lifesinger之前写过关于图片的HTTP请求的文章,不过他博客以前的数据没了。网上搜索到一篇:http://www.jb51.net/web/110275.html。 文章里面提到了用背景图和隐藏的img标签来预加载,调理很清晰。也可以作为参考。

另外,模仿新浪的cache.html自己写了个,如果喜欢把iframe作为独立文件使用的可以作为参考。


代码如下:

<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>
    <script>
    //usage: cache.html?v=123
    var win = window,
            doc = document,
            head = doc.getElementsByTagName("head")[0],
            getQuery = function(){
                    var ret = {},
                            sch = win.location.search,
                            arr,
                            tmp;
                    if (sch) {
                            sch = sch.substr(1);
                            arr = sch.split("&");
                            for(var i = 0, j = arr.length; i < j; i++) {
                                    tmp = arr[i].split('=');
                                    ret[tmp[0]] = tmp[1];
                            }
                    }
                    return ret;
            },
            version = getQuery().v || '';
    win.onerror = function(){return true}; //屏蔽js错误提示
    win.onload = function(){
            var b = doc.createElement("script");
            b.src = 'http://xx/1.js?v=' + version;
            head.appendChild(b);
            //...
    };
    doc.write('<link rel="stylesheet" href="http://xxx/3.css?version=' + version + '" \/>');
    </script>
    <img src="http://xxx/4.png" />
    </body></html>

(0)

相关推荐

  • js 实现图片预加载(js操作 Image对象属性complete ,事件onload 异步加载图片)

    看个例子: 复制代码 代码如下: <input type="button" name="" value="载入图片" onclick="addImg('tt.jpg')" /> <script type="text/javascript"> <!-- function addImg(isrc) { var Img = new Image(); Img.src = isrc; I

  • JS图片预加载插件详解

    在开发H5项目中有时候会遇到要加载大量图片的情况,利用预加载技术可以提高用户浏览时的体验. 1)概念: 懒加载也叫延迟加载:JS图片延迟加载,延迟加载图片或符合某些条件时才加载某些图片. 预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染. 2)区别: 两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载.懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力. 服务器端区别:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数.预加载可以说

  • js中Image对象以及对其预加载处理示例

    不显示在文档中的 Image 对象 对于不显示在文档中的 Image 对象时用 var 语句定义的: 复制代码 代码如下: var myImage = new Image();或 var myImage = new Image(<图片地址字符串>); 然后就可以像一般 Image 对象一样对待 myImage 变量了.不过既然它不显示在文档中,以下属性:lowsrc, width, height, vspace, hspace, border 就没有什么用途了.一般这种对象只有一个用:预读图片

  • js 利用image对象实现图片的预加载提高访问速度

    大量采用高解析度的图像的确可以让一个Web站点容光焕发.但同样也会造成站点访问速度下降--图片是文件,文件就要占用带宽,而带宽直接同访问等待时间相关.现在,让我们来学习一种名为图像预装载(image preloading)的小技巧来提高图像访问速度. 一些浏览器试图通过在本地缓存中保存这些图片来解决此问题.这样一来可以顺序调用这些图片--但对于首次使用这些图片的时候仍然会存在延时.预装载就是一种在需要图片之前就将图片下载到缓存的技术.采用这样的方式可以使当确实需要显示图片时迅速将其从缓存中恢复回

  • 利用CSS、JavaScript及Ajax实现高效的图片预加载

    方法一:用CSS和JavaScript实现预加载 实现预加载图片有很多方法,包括使用CSS.JavaScript及两者的各种组合.这些技术可根据不同设计场景设计出相应的解决方案,十分高效. 单纯使用CSS,可容易.高效地预加载图片,代码如下: 复制代码 代码如下: #preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; } #preload-02 { background:

  • javascript 也来玩玩图片预加载

    作者:编程浪子 最近玩图片预加载的人好像特别多,我也来一个,个人比较懒,只在IE上调试,大家就当无聊聊玩玩吧 IE图片预加载类 function LoadImageClass() { var me = this; var a = []; //图片数组 this.Idx = 0; //已经被加载的图片个数 this.Num = 0; //图片总数 //下载图片 this.LoadImages = function(s) { a = s.split(","); this.Num = a.l

  • 浅析js预加载/延迟加载

    Pre loader 预加载一般有两种常用方式:xhr和动态插入节点的方式.动态插入节点是最为简单也最为广泛的一种异步加载方式,然后使用动态插入节点方法加载的文件都会 在加载后立即执行,javascript的执行一方面会占用浏览器js执行进程,另一方面也可能改变页面结构,而css 的执行更有可能让整个页面变化.xhr方式虽然不会执行脚本,但是由于同域的限制 Lazy loader方式在一些图片非常多的网站中非常有用,在浏览器可视区域外的图片不会被载入,直到用户将页面滚动到它们所在的位置才加载,这

  • 纯JS图片批量预加载技术代码

    图片批量加载 function $id(id){ return document.getElementById(id);} function $c(tagName){ return document.createElement(tagName);} window.onload = function(){ imageLoad( { url:function(v){ v = []; for(var i=1; i [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

  • JS实现图片预加载无需等待

    网站开发时经常需要在某个页面需要实现对大量图片的浏览,如果考虑流量的话,大可以像pconline一样每个页面只显示一张图片,让用户每看一张图片就需要重新下载一下整个页面.不过,在web2.0时代,更多人愿意用javascript来实现一个图片浏览器,让用户无需等待过长的时间就能看到其他图片. 知道了一张图片的地址,需要把它在一个固定大小的html容器(可以是div等)里边显示出来,最重要的当然是需要知道这张即将显示的图片的宽和高,然后再结合容器的宽和高,按照一定的缩放比例使图片显示出来.因此,实

  • javascript 事件加载与预加载

    通常来说,window.onload就够用了,如果想加载多个事件,我们可以采取以下方式: 复制代码 代码如下: window.onload = function(){ func1(); func2(); func3(); //更多加载事件------ } 但如果由于某种特殊需要,我们不能合在一起写吗?如当前区域是面向管理员,后台生成页面时只有当用户是管理员,页面才生成这部分,而这部分也用到一些特殊的脚本,上面的方法就歇菜了! 复制代码 代码如下: //后台代码 <script type="

随机推荐