jQuery中的domReady分析

  我们都知道javascript中的window.onload方法的不足:必须等到所有图片和富文本媒体加载完后才能执行,影响用户体验。更好的做法是等到dom加载完即执行相应回调。类似jQuery中domReady方法应运而生。

  在jQuery中用这个方法非常简便:$(function(){}),这个其实是$(document).ready(function(){})的简便写法,见到源码:

rootjQuery = jQuery(document);
if ( jQuery.isFunction( selector ) ) {
  return rootjQuery.ready( selector );
}

  在简单的背后,是jQuery进行了封装,屏蔽了很多兼容性问题。我们来看看原生的domReady事件,了解下有那些坑。

  1,w3c的DOMContentLoaded,想说爱你不容易。

  本来是个好方法,奈何对于IE6,7,8,只能呵呵了。

  2,setTimeout

  setTimeout设置的函数, 会在readyState为complete时触发, 但是触发时间点是在图片资源加载完毕后.

  3,readyState

  readyState为interactive时, DOM结构并没有稳定, 此时依然会有脚本修改DOM元素, readyState为complete时, 图片已经加载完毕

  4,外部script(通过设置script的defer属性实现)

  外部script:如果将此script放在页面上方, 则无法稳定触发. 并且触发时DOM结构依然可能发生变化.

  5,doScroll(微软的文档只出doScroll必须在DOM主文档准备完毕时才可以正常触发. 所以通过doScroll判断DOM是否准备完毕)

  doScroll通过时readyState可能为interactive, 也可能为complete. 但是一定会在DOM结构稳定后, 图片加载完毕前执行

  方法很多,比较杂乱。jQuery的方法还是比较可取的,监听各种触发条件。宁可错杀一千,绝不放过一个。

  来看看源码的实现:

ready: function( fn ) {
    // Add the callback
    jQuery.ready.promise().done( fn );
    return this;
},

jQuery.ready.promise是个异步的Deffered对象,完成后触发回调fn。

Deferred对象什么时候完成呢?最好的结果当然是dom加载完后马上触发。这个时候就是各种监听方法。

jQuery.ready.promise = function( obj ) {
    if ( !readyList ) {
     readyList = jQuery.Deferred();
        // Catch cases where $(document).ready() is called after the browser event has already occurred.
        // we once tried to use readyState "interactive" here, but it caused issues like the one
        // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
        if ( document.readyState === "complete" ) {
            // Handle it asynchronously to allow scripts the opportunity to delay ready
            setTimeout( jQuery.ready );

        // Standards-based browsers support DOMContentLoaded
        } else if ( document.addEventListener ) {
            // Use the handy event callback
            document.addEventListener( "DOMContentLoaded", completed, false );

            // A fallback to window.onload, that will always work
            window.addEventListener( "load", completed, false );

        // If IE event model is used
        } else {
            // Ensure firing before onload, maybe late but safe also for iframes
            document.attachEvent( "onreadystatechange", completed );

            // A fallback to window.onload, that will always work
            window.attachEvent( "onload", completed );

            // If IE and not a frame
            // continually check to see if the document is ready
            var top = false;

            try {
                top = window.frameElement == null && document.documentElement;
            } catch(e) {}
        
            if ( top && top.doScroll ) {
                (function doScrollCheck() {
                    if ( !jQuery.isReady ) {

                        try {
                            // Use the trick by Diego Perini
                            // http://javascript.nwbox.com/IEContentLoaded/
                            top.doScroll("left");
                        } catch(e) {
                            return setTimeout( doScrollCheck, 50 );
                        }

                        // detach all dom ready events
                        detach();

                        // and execute any waiting functions
                        jQuery.ready();
                    }
                })();
            }
        }
    }
    return readyList.promise( obj );
};

多少判断,多少绑定......首先是判断document.readyState。如果是等于complete,立即执行回到

document.readyState === "complete"

根据浏览器的不同,分别绑定:

标准浏览器绑定:DOMContentLoaded,绑定load

document.addEventListener("DOMContentLoaded", completed, false)

window.addEventListener("load", completed, false)

IE浏览器下

document.attachEvent("onReadyStateChange", completed)

window.attachEvent("load", completed)

根据top.doScroll("left")判断是否加载完,加载完后直接触发:jQuery.ready();

再来看看completed方法

completed = function( event ) {

    // readyState === "complete" is good enough for us to call the dom ready in oldIE
    if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
        detach();
        jQuery.ready();
    }
},

还是触发jQuery.ready。最后来看看jQuery.ready

ready: function( wait ) {

    // Abort if there are pending holds or we‘re already ready
    if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
        return;
    }

    // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
    if ( !document.body ) {
        return setTimeout( jQuery.ready );
    }

    // Remember that the DOM is ready
    jQuery.isReady = true;

    // If a normal DOM Ready event fired, decrement, and wait if need be
    if ( wait !== true && --jQuery.readyWait > 0 ) {
        return;
    }

    // If there are functions bound, to execute
    readyList.resolveWith( document, [ jQuery ] );

    // Trigger any bound ready events
    if ( jQuery.fn.trigger ) {
        jQuery( document ).trigger("ready").off("ready");
    }
},

最后还是要触发回调:readyList.resolveWith( document, [ jQuery ] );

这个就是jQuery中domReady的实现。还是比较完美的。

优点是:加入了异步回调之后结构非常优美,想在哪里触发就在哪里触发。而且几乎全兼容。

缺点就是监听方法太多,对兼容性要求不高,不用这么费性能的方法。

参考文档:http://www.cnblogs.com/zhangziqiu/archive/2011/06/27/DOMReady.html

时间: 2024-10-26 08:40:43

jQuery中的domReady分析的相关文章

浅析Ajax跨域原理及JQuery中的实现分析

AJAX 的出现使得网页可以通过在后台与服务器进行少量数据交换,实现网页的局部刷新.但是出于安全的考虑,ajax不允许跨域通信.如果尝试从不同的域请求数据,就会出现错误.如果能控制数据驻留的远程服务器并且每个请求都前往同一域,就可以避免这些安全错误.但是,如果仅停留在自己的服务器上,Web 应用程序还有什么用处呢?如果需要从多个第三方服务器收集数据时,又该怎么办?  一.关于ajax跨域的思考 1.Ajax为什么不能跨域?到底是卡在哪个环节了?(下面项目中具体说,这里先说下结论). Ajax其实

jQuery中的bind() live() delegate()之间区别分析

jQuery中的bind() live() delegate()之间区别分析 首先,你得要了解我们的事件冒泡(事件传播)的概念,我先看一张图 1.bind方式 $('a').bind('click',function (){ alert('click'); }) 解析:这种方式最简单,jq扫描文档找出所有的a,让将函数绑定到每个元素的click事件上 2.live方式 $('a').live('click',function (){ alert('click'); }) 解析:jq将函数绑定到$

jquery中attr和prop的区别分析

这篇文章主要介绍了jquery中attr和prop的区别分析的相关资料,需要的朋友可以参考下 在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答案很多.这里谈谈我的心得,我的心得很简单: • 对于HTML元素本身就带有的固有属性,在处理时,使用prop方法. • 对于HTML元素我们自己自定义的DOM属性,在处理时,使用attr方法. 上面的描述也许有点模糊,举几个例子就知道了. 复制代码代

jQuery源码分析-jQuery中的循环技巧

Js代码   作者:nuysoft/JS攻城师/高云 QQ:47214707 EMail:[email protected] 声明:本文为原创文章,如需转载,请注明来源并保留原文链接. 前记:本文收集了jQuery中出现的各种遍历技巧和场景 Js代码   // 简单的for-in(事件) for ( type in events ) { } Js代码   // 缓存length属性,避免每次都去查找length属性,稍微提升遍历速度 // 但是如果遍历HTMLCollection时,性能提升非常

jQuery中hover与mouseover和mouseout的区别分析

本文实例分析了jQuery中hover与mouseover和mouseout的区别.分享给大家供大家参考,具体如下: 以前一直以为在jquery中其实mouseover和mouseout两个事件等于hover事件.两个没什么区别,应该是一样的.但昨天一个动画效果才让我见识了,这两个并不能等同. <div class="wrapper"> <div class="img"></div> <div class="tex

关于jquery中的bind()、live()、delegate()的区别分析浅析

近来在研究JS的时候,小码哥又一次看到jquery中常见的几种绑定事件的方法:bind(),live(),delegate().因此,闲来无事,想把他们几个做一下系统的分析,一遍后面的码农们能够一起分享! 先说好,鄙人也算是JS的初学者,很复杂的模块啥的,也是略懂而已,要是有码神看到,可别Ma我哈!! 那好,下面就直接进入主题了~ 首先,分别介绍一下这三个方法: 1.bind()--$(selector).bind(event,data,function);     event 为必需,规定添加

jQuery中删除节点方法remove()、detach()、empty()分析

jQuery中提供了三种删除节点的方法:remove().detach().empty(),本文详细分析这三种方法. 最容易区分的是empty(),该方法严格上属于“清空节点”,即删除其子节点,自身并不会删除.举个栗子: 1 <!doctype html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>remove和detach对

分析一下jquery中的ajax操作

在web前端开发中,ajax是很重要的一项技术,用原生写起来很是麻烦,需要一大堆js代码,而到了jq里就被精简了许多,一起来看看: jquery中的ajax分为三种方式: 1.$.get(),get方式获取 例子: $('.btn').click({ $.get('1.txt',function(data){ //'1.txt'为服务器上的文档,data为获取到的数据 alert(data); }); }) 2.$.post(),post方式获取 例子: $('.btn').click({ $.

jQuery中样式和属性模块简单分析

1.行内样式操作 目标:扩展框架实现行内样式的增删改查 1.1 创建 css 方法 目标:实现单个样式或者多个样式的操作 1.1.1 css方法 -获取样式 注意:使用 style 属性只能获取行内样式 解释:获取类或者外部样式文件中设置的样式要使用 W3C规范:window.getComputedStyle(dom) IE中 :dom.currentStyle itcast.fn.extend({ css: function(name, value) { return window.getCo