JavaScript判断DOM何时加载完毕的技巧


Posted in Javascript onNovember 11, 2012

处理HTML DOM文档存在一个难题是,JavaScript可以在DOM完全加载之前执行,这会给你的代码引发不少的潜在问题。浏览器的渲染和操作顺序大致如下列表:

HTML解析完毕
外部脚本和样式表加载完毕
脚本在文档内解析并执行
HTML DOM完全构造起来
图片和外部内容加载
网页完成加载

在网页头部并且从外部文件加载的脚本会在HTML真正构造之前执行。如前所述,这是个至关重要的问题,因为这两处执行的脚本并不能访问还不存在的DOM。幸好,我们还有若干的补救方法。
目前,最常用的级数是完全等待整个页面加载完毕才执行DOM操作。这种技术只需利用window对象的load事件来绑定一个函数,页面加载完毕即可触发。

addEvent(window, "load", function(){ 
// do something 
});

最简单的操作却是最慢的。在加载过程的顺序列表中,你会注意到页面的加载完毕与否完全被最后一步所掌控。这就是说,如果页面有很多的图片、视频等,用户可能得登上一段时间JavaScript才执行。
另一种级数可用以监听 DOM 加载状态,可能是最复杂的(从实现角度来看),但也是最有效地。
这项技术在不堵塞浏览器加载的情况下尽可能快地检查 HTML DOM文档是否已经加载了执行所必须得属性。以下是检查HTML DOM是否可用的几个要点:

document: 你需要知道DOM文档是否已经加载。若能足够快地检查,运气好的话你会看到undefined。
document.getElementsByTagName和document.getElementById:频繁使用document.getElementsByTagName和document.getElementById函数检查文档,当存在这些函数则表明DOM已经加载完毕。
document.body: 作为额外补充,检查元素是否已经完全加载。理论上前一个检查应该已经能做出判断,但我发现有些情况下还是不够。
使用这些检查就足够判断DOM是否可用了(“足够”在此表示可能会有一定毫秒级的时间差)。这个方法几乎没有瑕疵。单独使用前述检查,脚本应该可以在现代浏览器中运行得相对良好。但是,最近(2008年?)Firefox实现了缓存改进,使得window加载事件实际上可以在脚本能检查到DOM是否可用之前触发。为了能发挥这个优势,我同时为window加载事件附加检查,以期能获得更快的执行速度。

最后,domReady函数集合了所有需要在DOM可用时就执行的函数的引用。一旦DOM被认为是可用的,就调用这些引用并按顺序一一执行。

// 监听 DOM 是否可用的函数 
function domReady(f) { 
// 假如DOM已经加载,马山执行函数 
if(domReady.done) return f(); // 假如我们已经增加了一个函数 
if(domReady.timer) { 
// 把它假如待执行函数清单中 
domReady.ready.push(f); 
} else { 
// 为页面加载完毕绑定一个事件,以防它最先完成。 
addEvent(window, "load", isDOMReady); 
// 初始化执行函数的数组 
domReady.ready = [f]; 
// 尽可能快的检查DOM是否已可用 
domReady.timer = setInterval(isDOMReady, 13); 
} 
} 
// 检查 DOM 是否已可操作 
function isDOMReady() { 
// 如果我们能判断出DOM已可能,忽略 
if(domReady.done) return false; 
// 检查若干函数和元素是否可能 
if(document && document.getElementsByTagName && document.getElementById && document.body) { 
// 如果可用,我们停止检查 
clearInterval(domReady.timer); 
domReady.timer = null; 
// 执行所有正在等待的函数 
for(var i = 0; i < domReady.ready.length; i++) { 
domReady.ready[i](); 
// 记录我们在此已经完成 
domReady.ready = null; 
domReady.done = true; 
} 
} 
}

现在我们来看看在HTML文档中是如何执行的。假设已经将domReady函数写到一个名为domready.js的外部文件中
<html> 
<head> 
<title> Testing DOM Loading</title> 
<script src="domready.js"></script> 
<script> 
domReady(function(){ 
alert("The DOM is loaded!"); 
// do something 
}); 
</script> 
</head> 
<body> 
<h1>Testing DOM Loading</h1> 
<!-- 这里是大量的HTML --> 
</body> 
</html>
Javascript 相关文章推荐
AJAX的跨域与JSONP(为文章自动添加短址的功能)
Jan 17 Javascript
jQuery Mobile的loading对话框显示/隐藏方法分享
Nov 26 Javascript
jQuery学习笔记之jQuery原型属性和方法
Jun 09 Javascript
用循环或if语句从json中取数据示例
Aug 18 Javascript
浅谈javascript属性onresize
Apr 20 Javascript
AngularJS基础学习笔记之表达式
May 10 Javascript
浅谈js原生拖放
Nov 21 Javascript
JS数组去重常用方法实例小结【4种方法】
May 28 Javascript
Django+vue跨域问题解决的详细步骤
Jan 20 Javascript
layui 地区三级联动 form select 渲染的实例
Sep 27 Javascript
JavaScript文档加载模式以及元素获取
Jul 28 Javascript
微信小程序入门之指南针
Oct 22 Javascript
JavaScript中的匀速运动和变速(缓冲)运动详细介绍
Nov 11 #Javascript
jQuery语法总结和注意事项小结
Nov 11 #Javascript
javascript继承之为什么要继承
Nov 10 #Javascript
jquery表单验证使用插件formValidator
Nov 10 #Javascript
js 判断checkbox是否选中的操作方法
Nov 09 #Javascript
JS的replace方法详细介绍
Nov 09 #Javascript
获取div编辑框,textarea,input text的光标位置 兼容IE,FF和Chrome的方法介绍
Nov 08 #Javascript
You might like
一个简单的PHP&amp;MYSQL留言板源码
2020/07/19 PHP
探讨:如何编写PHP扩展
2013/06/13 PHP
php之readdir函数用法实例
2014/11/13 PHP
Javascript中的数学函数集合
2007/05/08 Javascript
js中top/parent/frame概述及案例应用
2013/02/06 Javascript
浏览器页面区域大小的js获取方法
2013/09/21 Javascript
防止按钮在短时间内被多次点击的方法
2014/03/10 Javascript
JavaScript中按位“异或”运算符使用介绍
2014/03/14 Javascript
jquery实现当滑动到一定位置时固定效果
2014/06/17 Javascript
对 jQuery 中 data 方法的误解分析
2014/06/18 Javascript
jquery渐隐渐显的图片幻灯闪烁切换实现方法
2015/02/26 Javascript
jQuery对象初始化的传参方式
2015/02/26 Javascript
JS实现的仿东京商城菜单、仿Win右键菜单及仿淘宝TAB特效合集
2015/09/28 Javascript
javascript使用 concat 方法对数组进行合并的方法
2016/09/08 Javascript
require.js与bootstrap结合实现简单的页面登录和页面跳转功能
2017/05/12 Javascript
Kindeditor单独调用多图上传实例
2017/07/31 Javascript
JS switch判断 三目运算 while 及 属性操作代码
2017/09/03 Javascript
Vue的事件响应式进度条组件实例详解
2018/02/04 Javascript
微信小程序地图导航功能实现完整源代码附效果图(推荐)
2019/04/28 Javascript
使用easyui从servlet传递json数据到前端页面的两种方法
2019/09/05 Javascript
Angular处理未可知异常错误的方法详解
2021/01/17 Javascript
Python中字典的基础知识归纳小结
2015/08/19 Python
解析Mac OS下部署Pyhton的Django框架项目的过程
2016/05/03 Python
python中logging库的使用总结
2017/10/18 Python
浅谈flask中的before_request与after_request
2018/01/20 Python
python调用OpenCV实现人脸识别功能
2018/05/25 Python
对python多线程中Lock()与RLock()锁详解
2019/01/11 Python
树莓派与PC端在局域网内运用python实现即时通讯
2019/06/22 Python
Django 项目通过加载不同env文件来区分不同环境
2020/02/17 Python
python小程序之4名牌手洗牌发牌问题解析
2020/05/15 Python
Windows环境下Python3.6.8 importError: DLLload failed:找不到指定的模块
2020/11/01 Python
Lookfantastic希腊官网:英国知名美妆购物网站
2018/09/15 全球购物
2014年效能监察工作总结
2014/11/21 职场文书
幼儿园奖惩制度范本
2015/08/05 职场文书
vue+echarts实现多条折线图
2022/03/21 Vue.js
详解MongoDB排序时内存大小限制与创建索引的注意事项
2022/05/06 MongoDB