[转载]document.readyState
原文:document.readyState
document.onreadystatechange
DOMContentLoaded
使用document.readyState
和document.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相关推荐
- 用 document.readyState == complete 判断页面是否加载完成。
传回XML 文件资料的目前状况. 基本语法 intState = xmlDocument.readyState; 说 明 这个属性是只读的,传回值有以下的可能: 0-UNINITIALIZED:XML ...
- window.onload和window.document.readystate的探究
在编写前端页面的时候,我们时常需要对页面加载的状态进行判断,以便进行相应的操作. 比如在移动端,时常需要在页面完全加载完成之前,先显示一个loading的图标,等待页面完成加载完成后,才显示出真正要展 ...
- js中常用方法以及document.readyState 判断页面是否加载完成 complete和interactive
传回XML 文件资料的目前状况. 基本语法 intState = xmlDocument.readyState; 说 明 这个属性是只读的,传回值有以下的可能: 0-UNINITIALIZED:X ...
- 用 document.readyState == complete 判断页面是否加载完成
说 明 这个属性是只读的,传回值有以下的可能: 0-UNINITIALIZED:XML 对象被产生,但没有任何文件被加载. 1-LOADING:加载程序进行中,但文件尚未开始解析. 2-LOADE ...
- document.readystate
http://www.cnblogs.com/lhb25/archive/2009/07/30/1535420.html http://www.cnblogs.com/haogj/archive/20 ...
- jquery中$(document).ready(function(){//todo});window.onload时间线关系
1.基于DOM的解析加载过程,即:document.readystate状态, 其有如下四个状态: a.uninitiated,未初始化状态. b.loading,dom开始解析. c.loaded, ...
- 真正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 ...
- 【javascript】DOM操作方法(3)——document节点属性
document.doctype //document.documentElement //来获取html元素 document.defaultView //返回document对象所在的window ...
- document.onreadystatechange()来判断页面加载完
document.onreadystatechange = subSomething;//当页面加载状态改变的时候执行这个方法. function subSomething() { if(doc ...
- 转载: Lodop、C-Lodop打印控件报错
在使用 Lodop.C-Lodop打印控件时,使用火狐浏览器不报错,换成IE浏览器时报404错误(找不到控件的下载位置): 以前的配置如下: 1.spring-servlet.xml中配置(找到打印控 ...
最新文章
- 《微信公众平台应用开发实战(第2版)》一导读
- 北京大学启用人脸识别系统:学生“刷脸”入校
- findbugs教程
- C和混编混合编程----strcpy缓存溢出原理
- oracle nvl和coalesce,NVL与Coalesce之间的Oracle差异
- python repusts模块_Python tslearn包_程序模块 - PyPI - Python中文网
- 【数码管识别】4识别成5或7的问题
- Win7 和 xp 双系统安装
- 怎么找网页源文件位置_网页源文件看不到swf或者MP3,怎么找音频文件真实地址、...
- MacBook 安装固态硬盘
- Deep Unordered Composition Rivals Syntactic Methods for Text Classification
- Post接口测试示例
- 第三篇,网络层的IP协议
- Google Earth网页版初探
- mulesoft Module 10 quiz 解析
- Android Studio的Android Device Monitor在哪儿?
- Linux的markdown笔记软件,3款免费好用的Markdown笔记应用,可以替代印象笔记
- 基于JAVA的聊天工具开发
- 三星账户联系人同步到手机上_如何将健身数据从Samsung Health同步到Google Fit
- 对英雄联盟比赛预测(二)- 数据获取api分析