window.onload方法,表示当页面所有的元素都加载完毕,并且所有要请求的资源也加载完毕才触发执行function这个匿名函数里边的具体内容。这样肯定保证了代码在domReady之后执行。使用window.onload方法在文档外部资源不多的情况下不会有什么问题,但是当页面中有大量远程图片或要请求的远程资源时,我们需要让js在点击每张图片时,进行相应的操作,如果此时外部资源还没有加载完毕,点击图片是不会有任何反应的,大大降低了用户体验。那既然window.onload方法不可行,又该怎么做呢?

你肯定想到了jquery中的$(document).ready(function(){})方法了,其实jquery中的domReady应该和window.onload的实现原理是大同小异的。为了解决window.onload的短板,w3c 新增了一个 DOMContentLoaded 事件。

(1)onload实现

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
window.onload=function(){
document.getElementById("header").style.color="red";
}
</script>
</head>
<body>
<h1 id="header">我是H1</h1>
<img src="1.jpg" alt="">
<img src="1.jpg" alt="">
<img src="1.jpg" alt="">
<!-- 如果大量图片的时候onload需要等待全部加载完成才能将h1标签给渲染成红色 -->
</body>
</html>

(2)Jquery解决以上问题

$(document).ready()方法和window.onload有什么区别?

(1)、window.onload方法是在网页中所有的元素(包括元素的所有关联文件)完全加载到浏览器后才执行的。

(2)、$(document).ready() 方法可以在DOM包括图片载入就绪时就对其进行操纵,并调用执行绑定的函数。

tip:jquery就是调用了原生JS事件DOMContentLoaded 来实现相同功能

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="jquery.js"></script>
<script>
$(document).ready(function(){
document.getElementById("header").style.color="red";
})
</script>
</head>
<body>
<h1 id="header">我是H1</h1>
<img src="1.jpg" alt="">
<img src="1.jpg" alt="">
<img src="1.jpg" alt="">
<!-- 假设大量远程图片正在加载 -->
</body>
</html>

(3)原生JS事件DOMContentLoaded实现

参考jquery中domReady的实现原理,来看一下javascript中domReady的实现策略。

JavaScript实现domReady功能,【domReady.js】兼容各浏览器通用版本的源代码:

function myReady(fn){
//对于现代浏览器,对DOMContentLoaded事件的处理采用标准的事件绑定方式
if ( document.addEventListener ) {
document.addEventListener("DOMContentLoaded", fn, false);
} else {
IEContentLoaded(fn);
}
//IE模拟DOMContentLoaded
function IEContentLoaded (fn) {
var d = window.document;
var done = false; //只执行一次用户的回调函数init()
var init = function () {
if (!done) {
done = true;
fn();
}
};
(function () {
try {
// DOM树未创建完之前调用doScroll会抛出错误
d.documentElement.doScroll('left');
} catch (e) {
//延迟再试一次~
setTimeout(arguments.callee, 50);
return;
}
// 没有错误就表示DOM树创建完毕,然后立马执行用户回调
init();
})();
//监听document的加载状态
d.onreadystatechange = function() {
// 如果用户是在domReady之后绑定的函数,就立马执行
if (d.readyState == 'complete') {
d.onreadystatechange = null;
init();
}
}
}
}

粘贴上面代码到新js文件保存。在页面中引入domReady.js文件,引用myReady(回调函数)方法即可。

用原生JS实现跟Jquery的ready相同功能效果:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="domReady.js"></script> <!--引用domReady功能 -->
<script>
myReady(function(){
document.getElementById("header").style.color="red";
})
</script>
</head>
<body>
<h1 id="header">我是H1</h1>
<img src="1.jpg" alt="">
<img src="1.jpg" alt="">
<img src="1.jpg" alt="">
<!-- 假设大量远程图片正在加载 -->
</body>
</html>

很明显,onload事件是要在所有请求都完成之后才执行,而domReady利用hack技术,在加载完dom树之后就能执行,所以domReady比onload执行时间更早,建议采用domReady。

(4)domReady与window.onload延迟差距测试

下面通过一个案例,来比较domReady与window.onload实现的不同,很明显,onload事件是要在所有请求都完成之后才执行,而domReady利用hack技术,在加载完dom树之后就能执行,所以domReady比onload执行时间更早,建议采用domReady。

    <!DOCTYPE html>
<html lang="zh-CN"> <head>
<meta charset="utf-8">
<title>domReady与window.onload</title>
<script src="domReady.js"></script>
</head> <body>
<div id="showMsg"></div>
<div>
<img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zofelhdj20xc0xc42s.jpg" alt="">
<img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zofahw3j20m80etq4a.jpg" alt="">
<img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zoi3ny6j20l20dw4gd.jpg" alt="">
<img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zog3tauj20m80et0uw.jpg" alt="">
<img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zofi2o5j20m80ettaq.jpg" alt="">
<img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zohjuvhj20tb0cdwvp.jpg" alt="">
</div>
<script>
var d = document;
var msgBox = d.getElementById("showMsg");
var imgs = d.getElementsByTagName("img");
var time1 = null,
time2 = null;
myReady(function() {
msgBox.innerHTML += "dom已加载!<br>";
time1 = new Date().getTime();
msgBox.innerHTML += "时间戳:" + time1 + "<br>";
});
window.onload = function() {
msgBox.innerHTML += "onload已加载!<br>";
time2 = new Date().getTime();
msgBox.innerHTML += "时间戳:" + time2 + "<br>";
msgBox.innerHTML += "domReady比onload快:" + (time2 - time1) + "ms<br>";
};
</script>
</body> </html>

执行结果对比,发现DomReady比onload快乐2秒左右。

解决window.onload延迟加载问题的更多相关文章

  1. jQuery基础之(三)jQuery功能函数前缀及与window.onload冲突

    1.jQuery功能函数前缀 在javascript中,开发者通常会编写一些小函数来处理各种操作细节,例如在用户提交表单时,要将文本框最前端和最末端的空格内容清理掉.而javascript中没有类似t ...

  2. JS:window.onload的使用介绍

    作者: 字体:[增加 减小] 类型:转载 时间:2013-11-13我要评论 window.onload在某些情况下还是比较实用的,比如加载时执行哪些脚本等等,下面有几个不错的示例,需要的朋友可以参考 ...

  3. 解决多人开发时使用window.onload的覆盖问题

    通用型小函数:解决多人开发时,同时使用window.onload事件所出现的后面的window.onload函数覆盖前面一个window.onload函数的问题. function addLoadEv ...

  4. 关于window.onload和body onload冲突的解决办法

    在学习用js在 页面中动态显示当前时间 和依次读取公告栏信息的 实验中 发现在将两个页面整合时 window.onload=function (){}和 <body onload="d ...

  5. window.onload和DOMContentLoaded的区别

    一.何时触发这两个事件? 1.当 onload 事件触发时,页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了. 2.当 DOMContentLoaded 事件触发时,仅当DOM加载完 ...

  6. window.onload和$(document).ready(function(){})的区别

    前段时间在面试之前查找并整理了一下window.onload和$(document).ready(function(){})区别,今天有时间更到我的博客上,由于本人资历尚浅,如有不对的地方,还请指正. ...

  7. window.onload与$(document).ready()的区别

    对于很多初学者来说,window.onload出现在代码中的频率非常高,这似乎变成了一种习惯,可是并不知道具体为什么要加这句代码,可以做几个试验对比: 实验一: <script> docu ...

  8. jquery mobile在页面加载时添加加载中效果 document.ready 和window.onload执行顺序比较

    想要添加这个效果,先来弄明白页面的加载和事件执行顺序,看这个简单例子: <html xmlns="http://www.w3.org/1999/xhtml"> < ...

  9. window.onload用法详解:

    网页中的javaScript脚本代码往往需要在文档加载完成后才能够去执行,否则可能导致无法获取对象的情况,为了避免这种情况的发生,可以使用以下两种方式: 一.将脚本代码放在网页的底端,这样在运行脚本代 ...

随机推荐

  1. 浅谈contentType = false

    转自https://segmentfault.com/a/1190000007207128 在刚接触 JQuery 中的 ajax 时,对其 contentType 并没有很在意,只是知晓它是代表发送 ...

  2. vim 高级功能

    本文章原创首发于公众号:编程三分钟 ,文末二维码. 文本编辑.跳转.删除.复制.替换这些操作用vim确实是快:但是好像仅仅是这样根本不能说服我vim超过鼠标的地方. 花点时间弄熟这些,除了炫技意外,主 ...

  3. android 端缓存清理的实现

    首先关于缓存清理,网上已经有太多的工具类,但是遗憾的是,基本上都不完善,或者说根本就不能用,而项目中又要求实现这个烂东西(其实这玩意真没一点屁用,毕竟第三方清理/杀毒软件都带这么一个功能),但是只好硬 ...

  4. .Net基础篇_学习笔记_第七天_Continue关键字的用法

    Continue: 立即结束本次循环,判断循环条件: 如果成立,则进行下一次循环,否则退出循环. Continue和break的区别: 遇到break,循环不继续. 遇到continue,本次循环也不 ...

  5. C# DATETIME格式转换汇总 根据日期过期星期

    C# DateTime.Now.Year --2019(年) DateTime.Now.Month --9(月) DateTime.Now.Day   --19(日) DateTime.Now.Hou ...

  6. Servlet接口的实现

    Servlet接口对Servlet进行了规范,定义了方法的主要范围. 1.public void init(ServletConfig servletConfig) (初始化) 参数的作用: (1)调 ...

  7. CSS——样式表的引入

    1.内部样式表 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...

  8. Recovery启动流程--recovery.cpp分析

    这篇文章主要通过分析高通recovery目录下的recovery.cpp源码,对recovery启动流程有一个宏观的了解. 当开机以后,在lk阶段,如果是recovery,会设置boot_into_r ...

  9. C. Anadi and Domino

    题目链接:http://codeforces.com/contest/1230/problem/C C. Anadi and Domino time limit per test: 2 seconds ...

  10. 前台提交数据到node服务器(post方式)

    post方式同样有两种办法,一种是表单提交,一种是ajax提交. 在此之前需要安装一个中间件:body-parser,安装好后在app.js头部引入: bodyParser = require('bo ...