xml地图|网站地图|网站标签 [设为首页] [加入收藏]

ready方法实现原理详解

来源:http://www.ccidsi.com 作者:集成介绍 人气:193 发布时间:2019-08-28
摘要:先分布一下jquery.ready()和window.onload,window.onload事件是在页面全数的财富都加载完结后触发的.假如页面上有大图片等能源响应缓慢,会导致window.onload事件迟迟无法触发.所以出现了DOM Rea

先分布一下jquery.ready()和window.onload,window.onload事件是在页面全数的财富都加载完结后触发的. 假如页面上有大图片等能源响应缓慢, 会导致window.onload事件迟迟无法触发.所以出现了DOM Ready事件. 那一件事件在DOM文书档案结构企图达成后触发, 即在财富加载前触发. 

只是,那么些事件不太可相信,举例当页面中存在图片的时候,或许反倒在 onload 事件随后本事接触,换言之,它只好科学地实践于页面不分包二进制能源或比非常少也许被缓存时作为三个策画吧。

(4)内部script: 外界script的改良版本. 外界script供给页面援用额外的js文件. 内部script方法能够幸免此难点.

参见: 

示范代码:

   1: //script defer    Dom Ready    

   2: document.write("<script id=__ie_onload defer src=javascript:void(0)></script>");

   3: var script = document.getElementById("__ie_onload");

   4: script.onreadystatechange = function() {

   5:     if (this.readyState == "complete") {                

   6:         document.getElementById("divMsg").innerHTML  = "<br/>internal script defer, readyState:"   document.readyState;

   7:     }

   8: };
DOMContentLoaded = function()
 {
  //取消事件监听,执行ready方法
 if ( document.addEventListener )
 {   
  document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
  jQuery.ready();
 }
  else if ( document.readyState === "complete" ) 
 {
  document.detachEvent( "onreadystatechange", DOMContentLoaded );
  jQuery.ready();
 }
};


jQuery.ready.promise = function( obj ) {
 if ( !readyList ) {

  readyList = jQuery.Deferred();
   //表示页面已经加载完成,直接调用 ready方法
  if ( document.readyState === "complete" ) { 
   //将 jQuery.ready压入异步消息队列,设置延迟时间1毫秒(注意,有些浏览器延迟不能小于4毫秒)
   setTimeout( jQuery.ready); 
  } 
  else if ( document.addEventListener ) //
  {
    //监听DOM加载完成
   document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
    //这里是为了确保所有ready执行结束,如果DOMContentLoaded方法执行了,将有一个状态值 isReady被设置为true,因此,
    //ready方法一旦执行,那么将只执行一次,window.addEventListener中的ready 将被 return 中断
   window.addEventListener( "load", jQuery.ready, false );

  } else {
   //低版本的IE浏览器
   document.attachEvent( "onreadystatechange", DOMContentLoaded );
   window.attachEvent( "onload", jQuery.ready );

   var top = false;

   try {
    top = window.frameElement == null && document.documentElement;
   } catch(e) {}

   if ( top && top.doScroll ) //剔除iframe的成分
   {
    (function doScrollCheck() {
     if ( !jQuery.isReady ) {

      try {
       //根据bug来兼容低版本的IE http://javascript.nwbox.com/IEContentLoaded/
       top.doScroll("left");
      } catch(e) {
       //由于低版本的IE 浏览器,onreadystatechange事件不可靠,因此需要根据各个bug来判断页面是否已加载完成
       return setTimeout( doScrollCheck, 50 ); 
      }

      jQuery.ready();
     }
    })();
   }
  }
 }
 return readyList.promise( obj );
};



ready: function( wait )
 {

 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { 
  //判断页面是否已完成加载并且是否已经执行ready方法
  return;
 }


 if ( !document.body ) {
  return setTimeout( jQuery.ready );
 }


 jQuery.isReady = true; //指示ready方法已被执行


 if ( wait !== true && --jQuery.readyWait > 0 ) {
  return;
 }


 readyList.resolveWith( document, [ jQuery ] );


 if ( jQuery.fn.trigger ) {
  jQuery( document ).trigger("ready").off("ready"); 
 }
},

第两种写法尽管简易了相当多,不过在成效上和率先种写法是等价的,假使您不信任,可以看一下 jQuery 的源代码中有如下代码片段:

IE8:

 

add DOM onload, readyState:interactive

external script defer (1), readyState:interactive

internal script defer, readyState:interactive

external script defer (2), readyState:interactive

add DOM in delay script, readyState:interactive

onreadystatechange, readyState:complete

jQuery ready, readyState:complete

window.onload, readyState:complete

setTimeout , readyState:complete

IE9:

 

add DOM onload, readyState:interactive

external script defer (1), readyState:interactive

internal script defer, readyState:interactive

external script defer (2), readyState:interactive

add DOM in delay script, readyState:interactive

jQuery ready, readyState:interactive

onreadystatechange, readyState:complete

window.onload, readyState:complete

setTimeout , readyState:complete

 

您大概感兴趣的篇章:

  • JavaScript的jQuery库中ready方法的就学课程
  • jQuery的ready方法详解
  • 仿照jQuery中的ready方法及落到实处按需加载css,js实例代码
  • javascript 模拟JQuery的Ready方法完毕并冒出的主题材料
  • jQuery的ready方法完结原理深入分析
DOMContentLoaded = function() {
  if ( document.addEventListener ) {
    document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
    jQuery.ready();
  } else if ( document.readyState === "complete" ) {
    // we're here because readyState === "complete" in oldIE
    // which is good enough for us to call the dom ready!
    document.detachEvent( "onreadystatechange", DOMContentLoaded );
    jQuery.ready();
  }
} 

DOM Ready 应用商量结论

测量检验结果见下边. 在此地先交给结论.

  • setTimeout设置的函数, 会在readyState为complete时接触, 但是接触时间点是在图片财富加载完结后.
  • readyState为interactive时, DOM结构并从未平安, 此时依然会有脚本修改DOM成分.
  • readyState为complete时, 图片已经加载完毕, 实验中对图片加载设置了延时.所以complete即使在window.onload前施行, 不过照旧太晚.
  • 表面script:要是将此script放在页面顶上部分, 则不可能牢固触发. 何况触发时DOM结构如故大概发生变化.
  • 中间script:与外界script同样的问题, 触发的岁月太早.
  • doScroll: doScroll通过时readyState可能为interactive, 也恐怕为complete. 不过一定会在DOM结构稳定性后, 图片加载完毕前推行.

据此能够看来, 最近的set提姆eout方法, 外界script和里面script方法, 都以存在不当的.应该说这么些格局不能够安全可相信的落到实处DomReady事件.

而独自利用readyState属性是力不胜任看清出Dom Ready事件的. interactive状态太早(DOM没有平安), complete状态过晚(图片加载实现).

jQuery达成中使用的doScroll方法是日前独一可用的方法.

在本文的最后, 提供了选择本原理完成的ready函数. 其实和jQuery中的Dom Ready原理大约一样. 不过里面出席了延时, 能够钦定win对象(即支持iframe)等作用.

多谢阅读,希望能接济到我们,感谢我们对本站的援救!

若是浏览器存在 document.onreadystatechange 事件,当该事件触发时,假若document.readyState=complete 的时候,可身为 DOM 树已经载入。

DOM Ready 概述    

深谙jQuery的人, 都知道DomReady事件. window.onload事件是在页面全数的能源都加载实现后触发的. 要是页面上有大图片等财富响应缓慢, 会导致window.onload事件迟迟不能触发.所以出现了DOM Ready事件. 那一件事件在DOM文档结构希图截至后触发, 即在能源加载前触发. 另外大家必要在DOM希图甘休后, 再修改DOM结构, 举个例子增多DOM成分等. 不然有相当的大可能率出现“Internet Explorer不能张开站点”的标题. 要效仿此错误, 能够在页面上增添下边包车型的士代码, 并用IE6打开:

<div>

    <script type="text/javascript">

        var div = document.createElement('div');

        div.innerHTML = "test";

        document.body.appendChild(div);

    </script>

</div>

    有关DOM Ready事件的完毕,包罗jQuery中的DomReady达成, 在境内和国外网址上业已早有人分享了经历, 并提议了大多方法.

为了幸免盲目从众, 抱着疑忌的神态, 笔者去研讨了那一个DOM Ready方法. 只会使用Google寻觅也许jQuery等类库, 不会支援前端开采人员升高.所以弄懂在那之中的原理才是关键.

对于FF, Chrome, Safari, IE9等浏览器:

DOMContentLoaded 事件在大多Webkit浏览器以及IE9上都得以选取, 这事件会在DOM文书档案计划好未来触发, 包蕴在HTML5行业内部中. 对于支持那件事件的浏览器, 直接行使DOMContentLoaded事件是最轻便易行最佳的选取.

对于IE6,7,8:

糟糕的是, IE6,7,8都不帮忙DOMContentLoaded事件.所以近日抱有的hack方法皆以为了让IE6,7,8支持DOM Ready事件.

鉴于下边包车型客车总计结果(贰零壹壹年七月总结的多寡), 我们亟须协理IE6,7,8, 缺一不可!

中华夏族民共和国某音乐站:

图片 1

CNZZ:

图片 2

其余是因为"360浏览器"的占有率, 还要支撑"360 IE6"这种无敌组合.

 

jQuery中的ready方法完结了当页面加载成功后才实行的功力,但他并不是window.onload大概doucment.onload的包裹,而是使用 标准W3C浏览器DOM遮掩api和IE浏览器缺欠来成功的,首先,大家来看jQuery的代码

(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);
    }

    // and execute any waiting functions
    jQuery.ready();
  }
})();

IE6:

 

add DOM onload, readyState:interactive

[external script defer(1), readyState:interactive--经常无此项]

internal script defer, readyState:interactive

[延时2秒加载js脚本]

add DOM in delay script, readyState:interactive

external script defer (2), readyState:interactive

jQuery ready, readyState:interactive

doScroll, readyState:interactive

[延时8秒加载图片]

onreadystatechange, readyState:complete

window.onload, readyState:complete

setTimeout , readyState:complete

率先个增加了defer的外界js, 时断时续. 当先一三个月华未有.

昨日闲来无事探讨商讨jQuery.ready()的里边贯彻,看JQ的源码五头雾水,由于自身很菜了,于是翻了翻牛人的播客,陈说详细,收获颇多。

那正是说,又是何人来调用呢?当然是索要的时候,在我们调用 ready 函数的时候,才须要注册这么些判别页面是不是完全加载的拍卖,这段代码在 1.8.3 中位居代码的 #244 行,如下所示:

(5)doScroll : 微软的文书档案只出doScroll必需在DOM主文档筹算完成时才方可健康触发. 所以通过doScroll剖断DOM是或不是计划实现.

参见: 

示范代码:

    //doScroll

    var doScrollMoniterId = null;

    var doScrollMoniter = function(){

        try{

            document.documentElement.doScroll("left");

            document.getElementById("divMsg").innerHTML  = "<br/>doScroll, readyState:"   document.readyState;

            if(doScrollMoniterId){

                clearInterval(doScrollMoniterId);

            }

        }

        catch(ex){

        }

    }

    doScrollMoniterId = setInterval(doScrollMoniter, 1);

 

 

你也许感兴趣的稿子:

  • 用javascript落成jquery的document.ready功能的落到实处代码
  • JQuery的ready函数与JS的onload的分裂详解
  • 宪章jQuery中的ready方法及贯彻按需加载css,js实例代码
  • JQuery的read函数与js的onload区别措施贯彻
  • javascript 模拟JQuery的Ready方法达成并冒出的标题
  • jQuery中的read和JavaScript中的onload函数的区分
  • 到家深入分析jQuery $(document).ready()和JavaScript onload事件
  • jquery $(document).ready() 与window.onload的区别
  • jQuery之$(document).ready()使用介绍
  • jQuery的Read()方法庖代原生JS详解

DOM Ready完结代码

上边是落到实处DOM Ready事件的函数代码, 与jQuery的相比较, 除了"__proxy函数"(在末端会讲课), 其余的注重函数都在ready的定义中, 易于掌握和维护. 並且自身完毕更为富有灵活性, 参与了时间延时已经传递window对象的本领:

        /**

        Dom Ready Event

        */

        ready : function( callback , delay, win){

            win = win || this.win || window;

            var doc = win.document;

            delay = delay || 0;

            this.domReadyMonitorRunTimes = 0;



            //将时间函数放入数组, 在DomReady时一起执行.

            this.readyFuncArray = this.readyFuncArray || [];

            this.readyFuncArray.push({func:callback, delay:delay, done:false});



            //domReadyMonitor为监控进程的事件处理函数

            var domReadyMonitor = (function(){

                var isReady = false;

                this.domReadyMonitorRunTimes  ;



                //对于非iframe嵌套的ie6,7,8浏览器, 使用doScroll判断Dom Ready.

                if(this.browser.ie && this.browser.ie<9 && !win.frameElement){

                    try {

                        doc.documentElement.doScroll("left");

                        isReady = true;

                    } 

                    catch(e) {

                    }

                }

                //非ie浏览器

                //如果window.onload和DOMContentLoaded事件都绑定失败, 则使用定时器函数判断readyState.                

                else if(doc.readyState==="complete" || this.domContentLoaded ){

                        isReady = true;

                }

                //对于某些特殊页面, 如果readyState永远不能为complete, 设置了一个最大运行时间5分钟. 超过了最大运行时间则销毁定时器.

                //定时器销毁不影响window.onload和DOMContentLoaded事件的触发.

                else{

                    if(this.domReadyMonitorRunTimes > 300000){

                        if(this.domReadyMonitorId){

                            win.clearInterval(this.domReadyMonitorId);

                            this.domReadyMonitorId = null;

                        }

                        return;

                    }

                }        





                //执行ready集合中的所有函数

                if(isReady){

                    try{

                        if(this.readyFuncArray && this.readyFuncArray.length){

                            for(var i=0, count=this.readyFuncArray.length; i<count; i  ){

                                var item = this.readyFuncArray[i];

                                if(!item || !item.func || item.done){

                                    continue;

                                }                                    

                                if(!item.delay){    

                                    item.done = true;

                                    item.func();

                                }

                                else{

                                    item.done = true;

                                    win.setTimeout(item.func, item.delay);

                                }

                            }

                        }

                    }

                    catch(ex){

                        throw ex;

                    }

                    finally{

                        if(this.domReadyMonitorId){

                            win.clearInterval(this.domReadyMonitorId);

                            this.domReadyMonitorId = null;

                        }

                    }

               }

            }).__proxy(this);    



            /**

            domContentLoadedHandler直接执行所有ready函数.

            没使用传参的形式是因为ff中的定时器函数会传递一个时间参数.

            */

            var domContentLoadedHandler = (function(){

                this.domContentLoaded = true;

                domReadyMonitor();

            }).__proxy(this);



            //启动DomReady监控进程

            if(!this.domReadyMonitorStarted){

                this.domReadyMonitorStarted = true;    

                this.domReadyMonitorId = win.setInterval( domReadyMonitor, 50);

                // Mozilla, Opera and webkit nightlies currently support this event

                if ( doc.addEventListener ) {

                    // Use the handy event callback

                    doc.addEventListener( "DOMContentLoaded", domContentLoadedHandler, false );

                    // A fallback to window.onload, that will always work

                    win.addEventListener( "load", domContentLoadedHandler, false );                

                }

                else if(doc.attachEvent){

                    // A fallback to window.onload, that will always work

                    win.attachEvent( "onload", domContentLoadedHandler, false );    

                }

            }                    

        }

地方的ready函数, 使用了三个Function对象的__proxy方法. 那是因为ready函数定义在一个接纳JSON格式创设的对象中:

var MyClass = {

    ready : function(){}

}

“__proxy”函数用于修改完结函数的this上下文, 与jQuery中的proxy函数类似, 不过为着利用越来越雅致的语法, 所以注入到了Function原型中. 如若无需修改this能够自行ready函数中对"___proxy"函数的正视.

"__proxy"函数代码如下:

            //扩展function函数原型。为所有的function对象添加proxy函数,用于修改函数的上下文。

            Function.prototype.__proxy = function(context){

                var method = this;

                return function () {

                    return method.apply(context || {}, arguments);

                };

            }; 

应用比方:

   1:  

   2: //正常使用

   3: this.U.ready( this.windowOnLoadHandler );

   4: //延时2秒加载

   5: this.U.ready(this.windowOnLoadDelayHandler, 2000);

转载:张子秋 http://www.cnblogs.com/zhangziqiu/ 
$(function() {
  // 从这里开始
});

(2)readyState: 判别readyState的景况是否为Complete, interactive等触发

以身作则代码:

   1: //onreadystatechange event

   2: document.onreadystatechange = function(e){

   3:     document.getElementById("divMsg").innerHTML  = "<br/> onreadystatechange, readyState:"   document.readyState;

   4:  

   5: };

 

(3)外界script: 通过安装了script块的defer属性完成.

参见: 

演示代码:

   1: <script type="text/javascript" src="ext-1.js" defer></script>

除开大家熟识的 onload 事件之外, 与 DOM 中的 onload 事件周边的,大家还应该有DOMContentLoaded 事件可以设想, 基于专门的职业的浏览器协助这么些事件,  当有着 DOM 深入分析完之后会接触这一个事件。

IE7:

 

add DOM onload, readyState:interactive

[external script defer(1), readyState:interactive--经常无此项]

internal script defer, readyState:interactive

add DOM in delay script, readyState:interactive

external script defer (2), readyState:interactive

onreadystatechange, readyState:complete

jQuery ready, readyState:complete

window.onload, readyState:complete

setTimeout , readyState:complete

率先个增添了defer的外部js, 陆陆续续. 超过叁分之一时日未有.

setTimeout 平日被用来做网页上的沙漏,允许为它钦赐二个阿秒数作为距离实践的时光。当被运转的主次须求在这些短的年华内运转,大家就能够给他钦命叁个十分小的流年数,可能须要及时试行的话,大家以致把那一个微秒数设置为0,但实际,setTimeout有二个极小推行时间,当内定的时辰低于该时间时,浏览器会用最小允许的时间作为setTimeout的时刻距离,也便是说即便大家把setTimeout的皮秒数设置为0,被调用的次第也从未立时运维。

(1)setTimeout : 在setTimeout中触发的函数, 一定会在DOM企图结束后触发.

亲自过问代码:

   1: //setTimeout Dom Ready

   2: var setTimeoutReady = function(){

   3:     document.getElementById("divMsg").innerHTML  = "<br/> setTimeout , readyState:"   document.readyState;

   4: };

   5: var setTimeoutBindReady = function(){

   6:     /in/.test(document.readyState)?setTimeout(arguments.callee, 1):setTimeoutReady();

   7: };

   8: setTimeoutBindReady();

标题来啦,我们的页面怎么时候企图好了吗?

DOM Ready 实现格局

首先总计一下当下IE下的DOM Ready方法:

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

  return this;
}

360 IE6:

 

add DOM onload, readyState:interactive

internal script defer, readyState:interactive

[延时2秒加载js脚本]

add DOM in delay script, readyState:interactive

jQuery ready, readyState:interactive

doScroll, readyState:interactive

[延时8秒加载图片]

onreadystatechange, readyState:complete

window.onload, readyState:complete

setTimeout , readyState:complete

增多了defer的的表面js都不曾奉行.

对360这种未有本领, 未有别的优点, 单纯的在IE上面加个外壳, 增多自个儿的出品和广告的浏览器, 应该给予鄙视! 固然依赖"安全警卫推荐用浏览器"据有了过多的境内市镇, 从运营和产品规模看是成功的, 不过却是不道德的. 所谓的"安全"只是贰个幌子而已! 真正精晓网络的客商不应有采用360浏览器. 360安全警卫是一款不错的出品, 最先的稳定很好. 只是近来越做越大, 手伸的尤其深. 挟顾客威逼商家的得利情势.不许别人出广告, 只可以自个儿产品出广告.当一款好的产品在一个未曾道德底线的人手里时, 顾客变得很难取舍.

    Browsers all have a 10ms minimum delay on OSX and a(approximately) 15ms delay on Windows.(在苹果机上的纤维时间距离是10阿秒,在Windows系统上的矮小时间间隔大约是15纳秒)

不过在看其余人写的 jQuery 代码的时候,经常又会看到如下写法:

本文由68399皇家赌场发布于集成介绍,转载请注明出处:ready方法实现原理详解

关键词: 68399皇家赌场 JavaScript

最火资讯