之前我们用的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);
});
分类: JavaScript 标签: DOM加载DOMContentLoadedonloadonreadystatechangereadyStatedeferdoScrollvoidsetInterval

评论

暂无评论数据

暂无评论数据

目录