原文:document.readyState

document.onreadystatechange

DOMContentLoaded

使用document.readyStatedocument.onreadystatechange搭配可以模拟出jquery ready和window.onload的效果。如果页面上有大图片等资源响应缓慢, 会导致window.onload事件迟迟无法触发.所以出现了DOM Ready事件. 此事件在DOM文档结构准备完毕后触发, 即在资源加载前触发.

1. document.readyState

1.1. 概述

一个document 的 Document.readyState 属性描述了文档的加载状态。

1.2. 值

一个文档的 readyState 可以是以下之一:

  • loading / 加载 。document 仍在加载
  • interactive / 互动。文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载
  • complete / 完成。T文档和所有子资源已完成加载。状态表示 load 事件即将被触发

当这个属性的值变化时,document 对象上的readystatechange 事件将被触发。

1.3. 语法

let string = document.readyState;// "complete"

1.4. 例子

不同的准备状态

switch (document.readyState) {case "loading":// The document is still loading.break;case "interactive":// The document has finished loading.// We can now access the DOM elements.var span = document.createElement("span");span.textContent = "A <span> element.";document.body.appendChild(span);break;case "complete":// The page is fully loaded.let CSS_rule = document.styleSheets[0].cssRules[0].cssText;console.log(`The first CSS rule is:${CSS_rule }`);break;
}
// 模拟 DOMContentLoaded/ jquery ready
document.onreadystatechange = function () {if (document.readyState === "interactive") {initApplication();}
}
// 模拟 load/onload 事件
document.onreadystatechange = function () {if (document.readyState === "complete") {initApplication();}
}

2. document.onreadystatechange

2.1. 概述

当一个文档的 readyState 属性发生更改时,readystatechange 事件会被触发。

2.2. 语法

document.onreadystatechange = funcRef;

funcRef 是个函数引用,会在readystatechange事件触发时调用.

2.3. 例子

/*
interactive / 互动
文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/readyState
​​​​​​​*/// 模拟DOMContentLoaded事件document.onreadystatechange = function () {if (document.readyState === "interactive") {initApplication();}
}

3. DOMContentLoaded

DOMContentLoaded在ie8及以下不支持。

DOMContentLoaded在jquery中有使用。

当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。另一个不同的事件 load 应该仅用于检测一个完全加载的页面。 在使用 DOMContentLoaded 更加合适的情况下使用 load 是一个令人难以置信的流行的错误,所以要谨慎。注意:DOMContentLoaded 事件必须等待其所属script之前的样式表加载解析完成才会触发。

模拟的css文件:CSS.php

<?php
sleep(3);

测试代码:

<link rel="stylesheet" href="css.php">
<script>document.addEventListener('DOMContentLoaded',function(){console.log('3 seconds passed');
});</script>

如果将link置于script之后,就会立即打印。

Note: 同步 JavaScript 会暂停 DOM 的解析。
Note: 还有许多通用和独立的库提供跨浏览器方法来检测 DOM 是否已准备就绪

3.1. 加速中

如果您希望 DOM 在用户请求页面后尽可能快地解析,你可以做的一些事情是把你的 JavaScript 异步化 以及 优化样式表的加载, 由于被并行加载而减慢页面加载,从主 html 文档“窃取”流量。

3.2. 示例

<script>document.addEventListener("DOMContentLoaded", function(event) {console.log("DOM fully loaded and parsed");});
</script>
<script>document.addEventListener("DOMContentLoaded", function(event) {console.log("DOM fully loaded and parsed");});for(var i=0; i<1000000000; i++){// 这个同步脚本将延迟DOM的解析。// 所以DOMContentLoaded事件稍后将启动。}
</script>

4. jquey.ready实现

参考:jQuery deferred.resolveWith() 方法

jQuery.holdReady()方法

4.1. 定义readyList等标识

  • readyList:待执行的回调函数队列。
  • isReady:DOM ready 是否已经完成标识
  • readyWait:
  • holdReady:jQuery.holdReady()方法
var// The deferred used on DOM ready// 一个用在 DOM ready 上的回调函数处理变量readyList,// Is the DOM ready to be used? Set to true once it occurs.// DOM ready 是否已经完成isReady: false,// A counter to track how many items to wait for before// the ready event fires. See #6781// 控制有多少个 holdReady 事件需要在 Dom ready 之前执行readyWait: 1,// Hold (or release) the ready event// 方法允许调用者延迟 jQuery 的 ready 事件// example. 延迟就绪事件,直到已加载的插件。//// $.holdReady(true);// $.getScript("myplugin.js", function() {//   $.holdReady(false);// });//holdReady: function(hold) {if (hold) {jQuery.readyWait++;} else {jQuery.ready(true);}},

4.2. ready定义

// Handle when the DOM is ready
ready: function(wait) {// Abort if there are pending holds or we're already ready// 如果需要等待,holdReady()的时候,把hold住的次数减1,如果还没到达0,说明还需要继续hold住,return掉// 如果不需要等待,判断是否已经Ready过了,如果已经ready过了,就不需要处理了。异步队列里边的done的回调都会执行了if (wait === true ? --jQuery.readyWait : jQuery.isReady) {return;}// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).// 确定 body 存在if (!document.body) {// 如果 body 还不存在 ,DOMContentLoaded 未完成,此时// 将 jQuery.ready 放入定时器 setTimeout 中// 不带时间参数的 setTimeout(a) 相当于 setTimeout(a,0)// 但是这里并不是立即触发 jQuery.ready// 由于 javascript 的单线程的异步模式// setTimeout(jQuery.ready) 会等到重绘完成才执行代码,也就是 DOMContentLoaded 之后才执行 jQuery.ready// 所以这里有个小技巧:在 setTimeout 中触发的函数, 一定会在 DOM 准备完毕后触发return setTimeout(jQuery.ready);}// Remember that the DOM is ready// 记录 DOM ready 已经完成jQuery.isReady = true;// If a normal DOM Ready event fired, decrement, and wait if need be// wait 为 false 表示ready事情未触发过,否则 returnif (wait !== true && --jQuery.readyWait > 0) {return;}// If there are functions bound, to execute// 调用异步队列,然后派发成功事件出去(最后使用done接收,把上下文切换成document,默认第一个参数是jQuery。readyList.resolveWith(document, [jQuery]);// Trigger any bound ready events// 最后jQuery还可以触发自己的ready事件// 例如://    $(document).on('ready', fn2);//    $(document).ready(fn1);// 这里的fn1会先执行,自己的ready事件绑定的fn2回调后执行if (jQuery.fn.trigger) {jQuery(document).trigger("ready").off("ready");}
},

4.3. 执行

其实逻辑不是很复杂,只是为了兼容不同的浏览器。

// $.ready()
jQuery.ready.promise = function(obj) {if (!readyList) {// 如果没有,新建一个 Deferred 对象// Deferred 用于处理异步延时回调函数,也就是内部用于 ready 的一个异步队列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:15if (document.readyState === "complete") {// Handle it asynchronously to allow scripts the opportunity to delay ready// setTimeout : 在setTimeout中触发的函数, 一定会在DOM准备完毕后触发.(即是 DOMContentLoaded)setTimeout(jQuery.ready);// Standards-based browsers support DOMContentLoaded// 支持 DOMContentLoaded 的浏览器 (除去ie 6 7 8)} else if (document.addEventListener) {// Use the handy event callback// 当检测的 document.readyState 的值不为 complete 时, 用 readystatechange 监听 document.readyState 值的变化事件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// 如果是 IE 浏览器(6、7、8)} else {// Ensure firing before onload, maybe late but safe also for iframesdocument.attachEvent("onreadystatechange", completed);// A fallback to window.onload, that will always workwindow.attachEvent("onload", completed);// If IE and not a frame// continually check to see if the document is ready// 如果是 IE 且不是在 frame 中var top = false;try {top = window.frameElement == null && document.documentElement;} catch (e) {}// 如果是IE并且不是iframeif (top && top.doScroll) {// 这里有个立即执行函数 doScrollCheck()(function doScrollCheck() {if (!jQuery.isReady) {try {// Use the trick by Diego Perini// http://javascript.nwbox.com/IEContentLoaded/// Diego Perini 在 2007 年的时候,报告了一种检测 IE 是否加载完成的方式,使用 doScroll 方法调用// 原理就是对于 IE 在非 iframe 内时,只有不断地通过能否执行 doScroll 判断 DOM 是否加载完毕// 在上述中间隔 50 毫秒尝试去执行 doScroll,注意,由于页面没有加载完成的时候,调用 doScroll 会导致异常,所以使用了 try - catch 来捕获异常// 直到DOM渲染结束了,这个时候 doScroll 方法不会抛出异常,然后就调用$.ready()top.doScroll("left");} catch (e) {return setTimeout(doScrollCheck, 50);}// detach all dom ready eventsdetach();// and execute any waiting functionsjQuery.ready();}})();}}}// 函数返回的是deferred对象,这就可以加上链式操作了// 可以使用 .done .fail 等方法return readyList.promise(obj);// Populate the class2type map
};

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

[转载]document.readyState相关推荐

  1. 用 document.readyState == complete 判断页面是否加载完成。

    传回XML 文件资料的目前状况. 基本语法 intState = xmlDocument.readyState; 说 明 这个属性是只读的,传回值有以下的可能: 0-UNINITIALIZED:XML ...

  2. window.onload和window.document.readystate的探究

    在编写前端页面的时候,我们时常需要对页面加载的状态进行判断,以便进行相应的操作. 比如在移动端,时常需要在页面完全加载完成之前,先显示一个loading的图标,等待页面完成加载完成后,才显示出真正要展 ...

  3. js中常用方法以及document.readyState 判断页面是否加载完成 complete和interactive

    传回XML 文件资料的目前状况.  基本语法 intState = xmlDocument.readyState;  说 明 这个属性是只读的,传回值有以下的可能: 0-UNINITIALIZED:X ...

  4. 用 document.readyState == complete 判断页面是否加载完成

    说 明 这个属性是只读的,传回值有以下的可能: 0-UNINITIALIZED:XML 对象被产生,但没有任何文件被加载.  1-LOADING:加载程序进行中,但文件尚未开始解析.  2-LOADE ...

  5. document.readystate

    http://www.cnblogs.com/lhb25/archive/2009/07/30/1535420.html http://www.cnblogs.com/haogj/archive/20 ...

  6. jquery中$(document).ready(function(){//todo});window.onload时间线关系

    1.基于DOM的解析加载过程,即:document.readystate状态, 其有如下四个状态: a.uninitiated,未初始化状态. b.loading,dom开始解析. c.loaded, ...

  7. 真正CSDN博客文章一键转载插件(含源码)

    插件地址:https://greasyfork.org/zh-CN/scripts/381053-csdn%E5%8D%9A%E5%AE%A2%E6%96%87%E7%AB%A0%E8%BD%AC%E ...

  8. 【javascript】DOM操作方法(3)——document节点属性

    document.doctype //document.documentElement //来获取html元素 document.defaultView //返回document对象所在的window ...

  9. document.onreadystatechange()来判断页面加载完

    document.onreadystatechange = subSomething;//当页面加载状态改变的时候执行这个方法. function subSomething()  {   if(doc ...

  10. 转载:  Lodop、C-Lodop打印控件报错

    在使用 Lodop.C-Lodop打印控件时,使用火狐浏览器不报错,换成IE浏览器时报404错误(找不到控件的下载位置): 以前的配置如下: 1.spring-servlet.xml中配置(找到打印控 ...

最新文章

  1. 《微信公众平台应用开发实战(第2版)》一导读
  2. 北京大学启用人脸识别系统:学生“刷脸”入校
  3. findbugs教程
  4. C和混编混合编程----strcpy缓存溢出原理
  5. oracle nvl和coalesce,NVL与Coalesce之间的Oracle差异
  6. python repusts模块_Python tslearn包_程序模块 - PyPI - Python中文网
  7. 【数码管识别】4识别成5或7的问题
  8. Win7 和 xp 双系统安装
  9. 怎么找网页源文件位置_网页源文件看不到swf或者MP3,怎么找音频文件真实地址、...
  10. MacBook 安装固态硬盘
  11. Deep Unordered Composition Rivals Syntactic Methods for Text Classification
  12. Post接口测试示例
  13. 第三篇,网络层的IP协议
  14. Google Earth网页版初探
  15. mulesoft Module 10 quiz 解析
  16. Android Studio的Android Device Monitor在哪儿?
  17. Linux的markdown笔记软件,3款免费好用的Markdown笔记应用,可以替代印象笔记
  18. 基于JAVA的聊天工具开发
  19. 三星账户联系人同步到手机上_如何将健身数据从Samsung Health同步到Google Fit
  20. 对英雄联盟比赛预测(二)- 数据获取api分析

热门文章

  1. 怎样删除服务器内磁盘阵列信息,如何管理你的磁盘阵列
  2. docker容器技术之虚拟化网络概述(四)
  3. 自然语言处理(NLP)概论
  4. 2020仙气十足的女生个性网名
  5. snf快速开发平台试用演示地址
  6. Android8.1 framework 微信付款码显示不出来
  7. [转] PHP开发通用型标题图片功能
  8. LWN:滚动发布的稳定版内核!
  9. “注释”是程序员的自我修养
  10. 六、Prometheus+Grafana搭建监控系统