javascript预加载和延迟加载
延迟加载javascript,也就是页面加载完成之后再加载javascript,也叫on demand(按需)加载,一般有一下几个方法:
What can your tired old page, once loaded and used and read, can do for your user? It can preload components needed by the next page, so when the users visit the next page, they have the new scripts, styles and images already in the cache. Next page loads faster and the user's happy. On its death bed you tired old page has left a good inheritance for future generations. Good old page.
How can you go about preloading for the next page? By waitingr onload of the current page and requesting the new components. Here are 4 ways to do so, all using a timeout of 1 sec foond after page load so that prefetching doesn't interfere with the user experience on the page.
One way... (DOM)
Using DOM you can create a new LINK element and a new SCRIPTelement and append them to the HEAD. For images - it's a one-liner new Image.src="..."
The drawback of this method is that your CSS is executed against the current page and might affect display. Same for JavaScript - it's executed. The image is simply requested and never displayed.
window.onload = function() {
setTimeout(function(){
// reference to <head>
var head = document.getElementsByTagName('head')[0];
// a new CSS
var css = document.createElement('link');
css.type = "text/css";
css.rel = "stylesheet";
css.href = "new.css";
// a new JS
var js = document.createElement("script");
js.type = "text/javascript";
js.src = "new.js";
// preload JS and CSS
head.appendChild(css);
head.appendChild(js);
// preload image
new Image().src = "new.png";
}, 1000);
};
For this way of doing it you can use any JavaScript library's helper methods to load stuff on demand. Good examples - YUI Get andLazyLoad
... or another ... (using iframe)
Another option is to create an iframe and append your components to its head. Using an iframe you can avoid the CSS potentially affecting the current page. JavaScript will still be executed.
window.onload = function() {
setTimeout(function(){
// create new iframe
var iframe = document.createElement('iframe');
iframe.setAttribute("width", "0");
iframe.setAttribute("height", "0");
iframe.setAttribute("frameborder", "0");
iframe.setAttribute("name", "preload");
iframe.id = "preload";
iframe.src = "about:blank";
document.body.appendChild(iframe);
// gymnastics to get reference to the iframe document
iframe = document.all ? document.all.preload.contentWindow : window.frames.preload;
var doc = iframe.document;
doc.open(); doc.writeln("<html><body></body></html>"); doc.close();
// create CSS
var css = doc.createElement('link');
css.type = "text/css";
css.rel = "stylesheet";
css.href = "new.css";
// create JS
var js = doc.createElement("script");
js.type = "text/javascript";
js.src = "new.js";
// preload CSS and JS
doc.body.appendChild(css);
doc.body.appendChild(js);
// preload IMG
new Image().src = "new.png";
}, 1000);
};
... I'm gonna find ya ... (static page in iframe)
If your components are static you can create a page that has them all and load that page into the dynamic iframe. Static means knowing them in advance, not relying on page's JavaScript to figure them out on the fly. As you can see, much simpler than the previous code.
window.onload = function() {
setTimeout(function(){
// create a new frame and point to the URL of the static
// page that has all components to preload
var iframe = document.createElement('iframe');
iframe.setAttribute("width", "0");
iframe.setAttribute("height", "0");
iframe.setAttribute("frameborder", "0");
iframe.src = "preloader.html";
document.body.appendChild(iframe);
}, 1000);
};
... I'm gonna GETcha, GETcha, GETcha! (with Ajax)
Finally - Ajax. Scripts are not executed, CSS not used for rendering. Nice and clean. For simplicty the code has no support for browsers that don't know what XMLHttpRequest is.
window.onload = function() {
setTimeout(function(){
// XHR to request a JS and a CSS
var xhr = new XMLHttpRequest();
xhr.open('GET', 'new.js');
xhr.send('');
xhr = new XMLHttpRequest();
xhr.open('GET', 'new.css');
xhr.send('');
// preload image
new Image().src = "new.png";
}, 1000);
};
Thanks!
Any other ways you can think of?
更多:http://www.phpied.com/preload-cssjavascript-without-execution/
async 属性(缺点是不能控制加载的顺序)
<script src="" async="true"/>
参考:
http://www.phpied.com/the-art-and-craft-of-postload-preloads/
http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/
今天看到了一章关于图片预加载的博文,其代码如下:
01 |
function loadImage(url, callback) |
02 |
{ |
03 |
var img = new Image(); //创建一个Image对象,实现图片的预下载 |
04 |
img.src = url; |
05 |
|
06 |
if (img.complete) |
07 |
{ // 如果图片已经存在于浏览器缓存,直接调用回调函数 |
08 |
callback(img); |
09 |
return; // 直接返回,不用再处理onload事件 |
10 |
} |
11 |
12 |
img.onload = function () { //图片下载完毕时异步调用callback函数。 |
13 |
callback(img); |
14 |
}; |
15 |
}; |
在网上搜索了一下相关文章,大体上都是这个思路。
这个方法功能是ok的,但是有一些隐患。
1. 创建了一个临时匿名函数来作为图片的onload事件处理函数,形成了闭包。
相信大家都看到过ie下的内存泄漏模式的文章,其中有一个模式就是循环引用,而闭包就有保存外部运行环境的能力(依赖于作用域链的实现),所以img.onload这个函数内部又保存了对img的引用,这样就形成了循环引用,导致内存泄漏。(这种模式的内存泄漏只存在低版本的ie6中,打过补丁的ie6以及高版本的ie都解决了循环引用导致的内存泄漏问题)。
2. 只考虑了静态图片的加载,忽略了gif等动态图片,这些动态图片可能会多次触发onload。
要解决上面两个问题很简单,其实很简单,代码如下:
1 |
img.onload = function () { //图片下载完毕时异步调用callback函数。 |
2 |
img.onload = null; |
3 |
callback(img); |
4 |
}; |
这样既能解决内存泄漏的问题,又能避免动态图片的事件多次触发问题。
在一些相关博文中,也有人注意到了要把img.onload 设置为null,只不过时机不对,大部分文章都是在callback运行以后,才将img.onload设置为null,这样虽然能解决循环引用的问题,但是对于动态图片来说,如果callback运行比较耗时的话,还是有多次触发的隐患的。隐患经过上面的修改后,就消除了,但是这个代码还有优化的余地:
1 |
if (img.complete) { // 如果图片已经存在于浏览器缓存,直接调用回调函数 |
2 |
callback(img); |
3 |
return; // 直接返回,不用再处理onload事件 |
4 |
} |
关于这段代码,看相关博文里的叙述,原因如下:
经过对多个浏览器版本的测试,发现ie、opera下,当图片加载过一次以后,如果再有对该图片的请求时,由于浏览器已经缓存住这张图片了,不会再发起一次新的请求,而是直接从缓存中加载过来。对于 firefox和safari,它们试图使这两种加载方式对用户透明,同样会引起图片的onload事件,而ie和opera则忽略了这种同一性,不会引起图片的onload事件,因此上边的代码在它们里边不能得以实现效果。
确实,在ie,opera下,对于缓存图片的初始状态,与firefox和safari,chrome下是不一样的(有兴趣的话,可以在不同浏览器下,测试一下在给img的src赋值缓存图片的url之前,img的状态),但是对onload事件的触发,却是一致的,不管是什么浏览器。产生这个问题的根本原因在于,img的src赋值与 onload事件的绑定,顺序不对(在ie和opera下,先赋值src,再赋值onload,因为是缓存图片,就错过了onload事件的触发)。应该先绑定onload事件,然后再给src赋值,代码如下:
1 |
function loadImage(url, callback) { |
2 |
var img = new Image(); //创建一个Image对象,实现图片的预下载 |
3 |
img.onload = function(){ |
4 |
img.onload = null; |
5 |
callback(img); |
6 |
} |
7 |
img.src = url; |
8 |
} |
这样内存泄漏,动态图片的加载问题都得到了解决,而且也以统一的方式,实现了callback的调用。
参考:http://www.nowamagic.net/javascript/js_ImagePreload.php
javascript预加载和延迟加载的更多相关文章
- JQUERY 插件开发——LAZYLOADIMG(预加载和延迟加载图片)
开发背景 本插件开发是近期写的最后一个插件了,接下来我想把最近研究的redis最为一个系列阐述下.当然Jquery插件开发是我个人爱好,我不会停止,在将来的开发中我会继续完善,当然也会坚持写这个系列的 ...
- js图片预加载与延迟加载
图片预加载的机制原理:就是提前加载出图片来,给前端的服务器有一定的压力. 图片延迟加载的原理:为了缓解前端服务器的压力,延缓加载图片,符合条件的时候再加载图片,当然不符合的条件就不加载图片. 预加载 ...
- ViewPager+Fragment取消预加载(延迟加载)(转)
原文:http://www.2cto.com/kf/201501/368954.html 在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragmen ...
- 用javascript预加载图片、css、js的方法研究
预加载的好处可以让网页更快的呈现给用户,缺点就是可能会增加无用的请求(但图片.css.js这些静态文件可以被缓存),如果用户访问的页面里面的css.js.图片被预加载了,用户打开页面的速度会快很多,提 ...
- ViewPager+Fragment取消预加载(延迟加载)
在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragment有个不好或者太好的地方.例如你在ViewPager中添加了三个Fragment,当加载V ...
- js图片预加载以及延迟加载
当我们需要做图片轮播的时候,如果让图片提前下载到本地,用浏览器缓存起来,我们可以用Image对象: function preLoadImg(){ var img=new Image(); img.sr ...
- js中的预加载与懒加载(延迟加载)
js中加载分两种:预加载与延迟加载 一. 预加载,增强用户的体验,但会加载服务器的负担.一般会使用多种 CSS(background).JS(Image).HTML(<img />) . ...
- javascript图片懒加载与预加载的分析
javascript图片懒加载与预加载的分析 懒加载与预加载的基本概念. 懒加载也叫延迟加载:前一篇文章有介绍:JS图片延迟加载 延迟加载图片或符合某些条件时才加载某些图片. 预加载:提前加载图片, ...
- 第一百五十七节,封装库--JavaScript,预加载图片
封装库--JavaScript,预加载图片 首先了解一个Image对象,为图片对象 Image对象 var temp_img = new Image(); //创建一个临时区域的图片对象alert ...
随机推荐
- php 代码重用
<?php /* 21.php * 代码重用 * include() required()载入文件 * include() 如果载入文件不存在,提示警告,还可以继续执行 * required() ...
- 关于淘宝的数据来源,针对做淘宝客网站的淘宝api调用方法
上次写了个淘宝返利模式的博客,直接被移除首页,不知道何故啊.可能是真的跟技术不太刮边. 众所周知,能够支撑一个网站运营的最基础不是程序写的多么好.也不是有多么牛X的运营人员,最主要的是数据,如果没有数 ...
- QT VS配置UNICODE问题
默认情况下,使用VSQT插件 导入.pro后,会自动在项目文件里面预定义好宏UNICODE,可以把该宏去掉,以免造成其他程序,使用多字节的代码出错 去除的两个方法 1.打开Propject->P ...
- asp.net mvc,做 301 永久重定向
以下代码为 asp.net mvc 4.0 代码做的 301 永久重定向 string url = “http://www.csdn.net/test.html” Response.StatusCod ...
- 【HDU】4092 Nice boat(多校第四场1006) ——线段树 懒惰标记
Nice boat Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) To ...
- 一道来自华为的C机试题目
题目是这样的 求一个字符串中连续字母的个数 比如I have a book. : 1 I have a dog. : 0 I haavee aa dogg : 4 #include <windo ...
- 微信小程序 app.json 配置
我们使用app.json文件来对微信小程序进行全局配置,决定页面文件的路径.窗口表现.设置网络超时时间.设置多 tab 等. 以下是一个包含了所有配置选项的简单配置app.json : { " ...
- 格而知之2:UIView的autoresizingMask属性探究
UIView的autoresizingMask属性,是用在当一个UIView实例的父控件的尺寸发生变化时,来自动调整UIView实例在父控件中的位置与尺寸的.autoresizingMask属性是一个 ...
- Java替代C语言的可能性
前不久CSDN刊登了一篇<C语言已经死了>的文章,引起了一些争论.事实上那篇文章是从Ed Burnette的博客上转载来的,原文题目是“Die, C, die!”,直译过来应该是& ...
- 【C++学习笔记1】
几个比较容易忘记的东西....... 移动构造函数: Vector(Vector &©) //移动构造函数 { if(copy.A!=NULL) { A=copy.A; cop ...