Javascript封装DOMContentLoaded事件实例_javascript技巧

最近在写一个Javascript的框架,刚把DOMContentLoaded事件封装好,略带小兴奋,把开发过程中遇到的原理和兼容性问题做篇笔记,省的忘记到处找。

我们在写js代码的时候,一般都会添加window.onload事件,主要是为了在DOM加载完后可以使用getElementById,getElementsByTagName等方法选取DOM元素进行操作,但是window.load会等到加载完DOM、脚本、CSS,最后加载完图片甚至是iframe中的所有资源才会触发,很多时候网页的图片较多较大,要等最后图片这个耗时大户加载完才执行js明显有些太迟了,很多时候都会影响用户体验。

很多js框架都有个document.ready的功能,像JQuery的$(document).ready()方法,可以在DOM加载完就立即执行js代码,让图片自个慢慢加载吧。

document.ready的核心是DOMContentLoaded事件,firefox、chrome、opera、safari、ie9+都可以使用addEventListener(‘DOMContentLoaded',fn,false)进行事件绑定,而ie6~8不支持DOMContentLoaded事件,所以要针对ie6~8做兼容性处理。

资料上说ie6~8可以使用document.onreadystatechange事件监听document.readyState状态是否等于complete来判断DOM是否加载完毕,如果页面中嵌有iframe的话,ie6~8的document.readyState会等到iframe中的所有资源加载完才会变成complete,此时iframe变成了耗时大户。但是经过测试,即使页面中没有iframe,当readyState等于complete时,实际触发的是onload事件而不是DOMContentLoaded事件,对这点表示惊奇。

还好ie有个特有的doScroll方法,当页面DOM未加载完成时,调用doScroll方法时,就会报错,反过来,只要一直间隔调用doScroll直到不报错,那就表示页面DOM加载完毕了,不管图片和iframe中的内容是否加载完毕,此法都有效。

如果有多个js文件绑定了document.ready事件,为了防止浏览器重复绑定,同时有序执行,可以引入一个事件队列机制来解决。

以上就是document.ready事件的原理和兼容性问题,下面贴段实例代码,为了方便理解执行过程,使用函数封装的模式,执行过程都写在注释里了,如果有不妥之处欢迎指教。

复制代码 代码如下:

//保存domReady的事件队列
eventQueue = [];

//判断DOM是否加载完毕
isReady = false;

//判断DOMReady是否绑定
isBind = false;

/*执行domReady()
 *
 *@param    {function}
 *@execute  将事件处理程序压入事件队列,并绑定DOMContentLoaded
 *          如果DOM加载已经完成,则立即执行
 *@caller
 */
function domReady(fn){
    if (isReady) {
        fn.call(window);
    }
    else{
        eventQueue.push(fn);
    };

    bindReady();
};

/*domReady事件绑定
 *
 *@param    null
 *@execute  现代浏览器通过addEvListener绑定DOMContentLoaded,包括ie9+
            ie6-8通过判断doScroll判断DOM是否加载完毕
 *@caller   domReady()
 */
function bindReady(){
    if (isReady) return;
    if (isBind) return;
    isBind = true;

    if (window.addEventListener) {
        document.addEventListener('DOMContentLoaded',execFn,false);
    }
    else if (window.attachEvent) {
        doScroll();
    };
};

/*doScroll判断ie6-8的DOM是否加载完成
 *
 *@param    null
 *@execute  doScroll判断DOM是否加载完成
 *@caller   bindReady()
 */
function doScroll(){
    try{
        document.documentElement.doScroll('left');
    }
    catch(error){
        return setTimeout(doScroll,20);
    };
    execFn();
};

/*执行事件队列
 *
 *@param    null
 *@execute  循环执行队列中的事件处理程序
 *@caller   bindReady()
 */
function execFn(){
    if (!isReady) {
        isReady = true;
        for (var i = 0; i < eventQueue.length; i++) {
            eventQueue[i].call(window);
        };
        eventQueue = [];
    };
};

//js文件1
domReady(function(){
    ...
});
//js文件2
domReady(function(){
    ...
});

//注意,如果是异步加载的js就不要绑定domReady方法,不然函数不会执行,
//因为异步加载的js下载之前,DOMContentLoaded已经触发,addEventListener执行时已经监听不到了

测试页面:都加载了两张很大的图片,onload需要图片加载完才能执行js,DOMContentLoaded只需等到DOM加载完即可执行js。可以打开firebug查看加载过程,每次测试前记得先清理下浏览器缓存。

时间: 2024-09-01 15:51:19

Javascript封装DOMContentLoaded事件实例_javascript技巧的相关文章

Javascript封装DOMContentLoaded事件实例

  这篇文章主要介绍了Javascript封装DOMContentLoaded事件实例,DOMContentLoaded是FF,Opera 9的特有的Event, 当所有DOM解析完以后会触发这个事件,需要的朋友可以参考下 最近在写一个Javascript的框架,刚把DOMContentLoaded事件封装好,略带小兴奋,把开发过程中遇到的原理和兼容性问题做篇笔记,省的忘记到处找. 我们在写js代码的时候,一般都会添加window.onload事件,主要是为了在DOM加载完后可以使用getEle

JavaScript监听和禁用浏览器回车事件实例_javascript技巧

js监听浏览器回车事件,可以支持ie6+,火狐,谷歌等浏览器. 复制代码 代码如下: <html> <head> <script type="text/javascript"> //注册键盘事件 document.onkeydown = function(e) {  //捕捉回车事件  var ev = (typeof event!= 'undefined') ? window.event : e;  if(ev.keyCode == 13) {  

深入理解Javascript封装DOMContentLoaded事件

我们在写js代码的时候,一般都会添加window.onload事件,主要是为了在DOM加载完后可以使用getElementById,getElementsByTagName等方法选取DOM元素进行操作,但是window.load会等到加载完DOM.脚本.CSS,最后加载完图片甚至是iframe中的所有资源才会触发,很多时候网页的图片较多较大,要等最后图片这个耗时大户加载完才执行js明显有些太迟了,很多时候都会影响用户体验. 很多js框架都有个document.ready的功能,像JQuery的$

javascript加减乘除的简单实例_javascript技巧

javascript加减乘除的简单实例 <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> </head> <script language="javascript" type="text/javascript"> //除法函数 function accD

javascript常用的正则表达式实例_javascript技巧

小编之前整理了不少JavaScript常用的正则表达式实例,都是自己用的,现在放出来给大家分享下. 复制代码 代码如下: /*** 取得字符串的字节长度*/      function strlen(str)       {           var i;           var len;           len = 0;           for (i=0;i<str.length;i++)           {               if (str.charCodeAt(

javascript拖拽应用实例_javascript技巧

之前文章中也讲了一下拖拽的基本思想,理论是有了,那实践呢,可以运用到什么地方呢?下面就给大家带来一个用拖拽思想写的一个小实例,供大家参考,大致效果看下图: 就是这样一个简单的一个拖拽条,你可以把它理解为滚动条,也可以理解为表单中的数量选择控件,也可以理解为进度条,等等,反正你可以改成很多你想要的效果,废话不多说,我们来看看这个是怎么做的吧! 想了想,感觉原理就不用说了吧,我在拖拽效果中就已经说的很清楚了,不清楚的同学可以出门左转,查看 javascript小实例,PC网页里的拖拽 ,我就直接贴代

js操作滚动条事件实例_javascript技巧

本文实例讲述了js操作滚动条事件的方法.分享给大家供大家参考.具体分析如下: 之前一直很纳闷,如何监视滚动条的事件,今天终于有点明白了. 下边代码,是监听滚动条只要移动,下方的返回顶部的div显示与隐藏的代码 window.onscroll = function () { var t = document.documentElement.scrollTop || document.body.scrollTop; if (t > 0) { $(".cbbfixed").css(&q

浅析javascript中的事件代理_javascript技巧

本文的主要内容是根据前不久面试某家公司Web前端开发岗位,面试时做的一道数组去重问题的解题思路进行整理的,分享给大家. 题目本身很简单:一个ul中有一千个li,如何给这一千个li绑定一个鼠标点击事件,当鼠标点击时alert出这个li的内容和li的位置坐标xy, <ul id="ulItem"> <li id="li1">1</li> <li id="li2">2</li> <li

JavaScript之AOP编程实例_javascript技巧

本文实例讲述了JavaScript之AOP编程.分享给大家供大家参考.具体如下: /* // aop({options}); // By: adamchow2326@yahoo.com.au // Version: 1.0 // Simple aspect oriented programming module // support Aspect before, after and around // usage: aop({ context: myObject, // scope contex