首页 » JavaScript » JS DOM加载(上)

最后更新于 2018年12月10日

之前我们用的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);
});
  • weixiao kaixin tushetou jingkong deyi fanu liezui liuhan daku ganga bishi nanguo lihai qian yiwen numu tu yi haixiu se fadai minyan hehe henkaixin huaji biyiyan kuanghan maimeng shui xiaku penqi zhangzui pen aini ye niu laji ok chigua renshi kongbu shuai xiaoxiese touxiao huaixiao jingnu chihuai kaisang xiaoku koubi zhuangbi lianhong kanbujian shafa zhijing xiangjiao dabian yaowan redjing lazhu rizhi duocang chixigua hejiu xixi xiaopen goukun xiaobuchu shenme wusuowei guancha lajing chouyan xiaochi bie zhadanzui zhadanxiao