JS DOM加载(上)
之前我们用的js都是在window.onload事件里面使用的,但是这样会有一个问题,如果页面的内容一直没有加载完毕,我们的js就无法使用,这就很头疼了,我目前为博客加的两个js效果就是处于未加载完毕就无法运行的尴尬局面。
解决办法:
DOMContentLoaded方法
w3c提供了一个事件为DOMContentLoaded;这个事件是在浏览器解析完文档便能触发。
那么这个浏览器解析文档是一个什么样的处理过程呢,就是相当于已经把html元素都过了一遍,页面已经初具雏形了,但是一些外部资源,例如图片这些还在加载中,这时便会触发DOMContentLoaded事件。
简单点来说DOMContentLoaded触发优先于图片的完整加载之前,也就说会优先于window.onload事件。
那么我们在DOMContentLoaded事件下也可以通过getElementById()这些方法来获取元素了,于是:
addEvent(document, 'DOMContentLoaded', function() {
var box = document.getElementById('box');
alert(box.innerHTML);
removeEvent(document, 'DOMContentLoaded', arguments.callee)
});
addEvent是作为调用的函数保存的,并没有放在window.onload事件下,所以可以直接调用,只要这个addEvent函数是在你调用之前的就行。
arguments.callee意思是返回这个被执行的函数,这样就可以删除匿名函数的事件了。
创建script方法
以上的写法可以解决js在网页完全加载完毕之前无法运行的问题,但是旧版ie浏览器不支持DOMContentLoaded,所以这里还要想办法兼容。
这里我们不使用window.onload来做ie的兼容,而是使用另一种方法。
document.write('<script id="ie_loaded" defer="defer" src="javascript:void(0)"></script>');
var ie_loaded = document.getElmentById('ie_loaded');
ie_loaded.onreadystatechange = function() {
if (this.readyState == 'complete') {
var box = document.getElementById('box');
alert(box.innerHTML);
}
};
给dom添加一个script元素,添加defer属性,src等于javascript:void(0);
javascript:void(0)的意思是,运行内联的javascript代码void(),void()表示不返回任何值,但是括号里的内容还是正常执行的,为了不让他执行,我们写个数字就行了,括号里也可以不写任何东西,但是大部分人都是写个0表示阻止,这里就随大流了。
defer属性和async属性有点相似,但是本质又不同。
defer表示页面被解析完毕后才会执行,而async则是谁先加载完谁先执行,可能表达不是很准确,但是意思差不多。
在这里我们要获取到dom上元素,所以要使用defer属性,当script元素插入到dom中后,我们获取到它,然后通过onreadystatechange获取加载的状态,通过readyState返回的状态值进行判断,如果返回了complete,表示加载完毕,加载完毕说明文档已经解析完毕了(defer起了作用),然后就开始运行需要的js。
doScroll方法
ie这样写其实还会有一个bug,就是当页面有iframe元素存在是会失去原来的效果,无法正常运行。
那么我们要使用ie独有的一个doScroll('left'),这个属性在ie解析完文档后才能调用,那么我们只要判断这个方法能够正常执行,就说明文档已经解析完毕了。
var timer = null;
timer = setInterval(function() {
try {
document.documentElement.doScroll('left');
var box = document.getElementById('box');
alert(box.innerHTML);
}catch(e) {
//跳过
};
});
这里我们创建一个变量,变量为一个间歇调用函数,我们在里面创建一个函数,但是不设置间歇调用的时间,这样他就会不断的运行这个函数。
通过调试错误的函数try来判断,运行doScroll出错,调到catch,不做任何操作,然后不断的重复,知道doScroll不出错了,才运行下面的代码。
但是这个间歇调用还在不断的调用,这里我们下一章再讲。
兼容写法:
function addDomLoaded(fn) {
if(document.addEventListener) {
addEvent(document,'DOMContentLoaded',function(){
fn();
removeEvent(document, 'DOMContentLoaded', arguments.callee);
})
}else {
var timer = null;
timer = setInterval(function() {
try {
document.documentElement.doScroll('left');
fn();
}catch(e) {
//跳过
};
});
}
}
//调用函数
addDomLoaded(function(){
var box = document.getElementById('box');
alert(box.innerHTML);
});
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据