今天写了一个小例子,但是出了一个错误:
Uncaught TypeError: Cannot read property ‘style’ of null。
代码如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试例</title>
<style type="text/css">
div{
width:200px;
height:200px;
border:2px solid black;
background-color:red;
}
</style>
<script type="text/javascript">
var d=document.getElementById('myDiv');
d.style.backgroundColor="blue";
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
从这个错误来看,应该是使用的getElementById方法没有获取到div元素,如下:
查阅了一些资料,猜想应该是DOM树创建与渲染的问题。HTML文档只是用来显示内容的,行为操作还是要通过DOM实现而HTML标签要通过浏览器解析才能变成DOM节点。出现这个问题应该是运行脚本时DOM树还未创建完成,所以将脚本改为如下所示: 查阅了一些资料,猜想应该是DOM树创建与渲染的问题。HTML文档只是用来显示内容的,行为操作还是要通过DOM实现而HTML标签要通过浏览器解析才能变成DOM节点。出现这个问题应该是运行脚本时DOM树还未创建完成,所以将脚本改为如下所示:
<script type="text/javascript">
window.onload=function(){
var d=document.getElementById('myDiv');
d.style.backgroundColor="blue";
}
</script>
此时发现背景颜色发生了变化,程序错误消失了,证明真的是DOM树创建的问题。于是去查了相关资料。发现使用onload还是会有一些缺陷,onload表示当页面所有元素加载完毕后才执行,所以当页面图片很多的情况下,载入图片耗费的时间较长,onload距离执行的时间越慢,影响用户体验,此时还可以使用domReady。domReady表示DOM树加载完毕执行,而不包括图片,iframe,flash等元素,只要DOM标签加载完毕则运行。如果我们需要在DOM树生成后并且其他资源加载以及渲染前就执行js代码的话,domReady是最好的选择。
W3C提供了一个DOMContentLoaded事件,该方法与onload相比触发时间更早,页面加载完DOM后立刻触发,但只有IE 9以上才支持这一事件。IE6,7,8都不支持DOMContentLoaded事件。以下是一个慕课教程中实现的IE6,7,8的domReady方法。对于现代浏览器则使用标准事件绑定方法直接绑定DOMContentLoaded事件:
if(document.addEventListener){
document.addEventListener(‘DOMContentLoaded’,fn,false);
}
IE下需模拟DOMContentLoaded:
function IEContentLoaded(fn){
var d=window.document;
var done=false;
var init=function(){
if(!done){
done=true;
fn();
}
};
(function(){
try{
d.documentElement.doScroll('left');
}
catch(e){
setTimeout(arguments.callee,50);
return;
}
init();
})();
d.onreadystatechange=function(){
if(d. readyState=='complete'){
d.onreadystatechange=null;
init();
}
}
}
关于以上代码中的几点注释:
onreadystatechange事件的目的是提供与文档或元素加载状态有关的信息,支持这个事件的对象有一个readyState属性,当属性值为complete表示对象已加载完毕。
doScroll:微软指出doScroll必须在DOM主文档准备完毕时才可以正常触发,所以通过doScroll判断DOM是否准备完毕。
总的来说,domReady方法实现如下:
function myReady(fn){
if(document.addEventListener){
document.addEventListener(‘DOMContentLoaded’,fn,false);
}
else{
IEContentedLoaded(fn);
}
}
测试该domReady方法是否可行:
<script src="domReady.js"></script>
<script type="text/javascript">
myReady(function(){
var d=document.getElementById('myDiv');
d.style.backgroundColor="blue";
});
</script>
测试onload与domReady:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试例</title>
<style type="text/css">
div{
width:800px;
height:200px;
border:2px solid black;
background-color:red;
}
</style>
<script src="domReady.js"></script>
<script type="text/javascript">
myReady(function(){
var d=document.getElementById('myDiv');
d.innerHTML+="DOM已加载!<br>";
time1=new Date().getTime();
d.innerHTML += "时间戳:"+time1+"<br>";
});
window.onload=function(){
var d=document.getElementById('myDiv');
d.innerHTML += "onload已加载!<br>";
time2=new Date().getTime();
d.innerHTML += "时间戳:"+time2+"<br>";
d.innerHTML += "domReady比onload快:"+(time2-time1)+"ms<br>";
};
</script>
</head>
<body>
<div id="myDiv"></div>
<div>
<img src="img/12.jpg" />
<img src="img/13.jpg" />
<img src="img/14.jpg" />
<img src="img/15.jpg" />
<img src="img/16.jpg" />
<img src="img/17.jpg" />
</div>
</body>
</html>