domReady的理解
domReady的理解
domReady是名为DOMContentLoaded事件的别称,当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表、图像和子框架的完全加载。
描述
浏览器渲染DOM结构是有一定顺序的,虽然不同浏览器的实现各有不同,但是基本流程都大致相同:
- 自上而下,首先解析
HTML标签,生成DOM Tree。 - 在解析到
<link>或者<style>标签时,开始解析CSS,生成CSSOM,值的注意的是此时解析HTML标签与解析CSS是并行执行的。 - 当遇到
<script>标签后,浏览器会立即开始解析脚本,并停止解析文档,因为脚本有可能会改动DOM与CSS,继续解析会浪费资源,所以应当将<script>标签放于<body></body>后。 - 当
DOM Tree与CSSOM生成后,将两者结合进行布局,计算它们的大小位置等布局信息,形成一个能够表示这所有信息的内部表示模型,可称为渲染树render tree。 - 根据计算好的信息绘制整个页面,系统会遍历渲染树,并调用
paint方法,将内容显示在屏幕上。
在浏览器解析DOM结构的过程中是存在阻塞过程的:
- 解析
JavaScript过程中会阻塞浏览器的解析过程,准确来说解析渲染过程与解析JavaScript的过程是互斥的。 CSS加载解析时不会阻塞DOM树的解析过程,这两个解析过程是可以并行的,但是CSS加载过程中是不能进行JavaScript的解析的,也就是说CSS加载过程中是会阻塞JavaScript的解析,此外因为生成Render Tree时需要CSSOM,所以在DOM Tree解析完成而CSSOM未完成时不会继续生成Render Tree。- 解析
HTML结构同样不会阻塞CSS解析的过程,也同样不会和JavaScript的解析过程并行执行,并且DOM Tree解析未完成而CSSOM完成时同样不会继续生成Render Tree。 - 使用异步加载的
<script>标签是不会阻塞DOM解析的,当然其就不会阻塞DOMContentLoaded事件的触发,但是依旧会阻塞load事件的触发。
再来看一下DOMContentLoaded事件与load事件的触发时机:
- 当初始的
HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表、图像和子框架的完全加载。关于触发的时机,如果文档中全部为HTML与CSS则DomContentLoaded事件无需等到CSS加载完毕即可触发;当Js都在CSS之前DomContentLoaded事件无需等到CSS加载完毕即可触发,当然解析CSS与DOM是需要等待前边的Js解析完毕的;当Js在CSS之后时,则DomContentLoaded事件需等到CSS与Js加载完毕才能够触发,上文也提到了CSS的加载会阻塞Js的加载,而Js标签本身也属于DOM结构,必须等待其加载完成之后才能触发DomContentLoaded事件;异步加载的<script>标签不会阻塞DOMContentLoaded事件。 - 当整个页面及所有依赖资源如样式表和图片都已完成加载时,将触发
load事件。不使用动态加载的<iframe>同样会阻塞load事件,此外即使是异步加载的<script>标签同样会阻塞load事件。
在各种条件下重新整理一下页面加载的过程,主要是在于DOMContentLoaded事件与load事件触发的时间线:
- 自上而下,首先解析
HTML标签,生成DOM Tree,此时document.readyState = "loading"。 - 在解析到
<link>或者<style>标签时,开始解析CSS,生成CSSOM,值的注意的是此时解析HTML标签与解析CSS是并行执行的。 - 解析到没有设置异步加载的
<script>的时候,阻塞文档解析,等待Js脚本加载并且执行完成后,才会继续解析文档。 - 解析到异步
<script>的时候不阻塞解析文档,继续向下解析,defer属性会使Js文件等待DOM Tree构建完成之后再执行,而async属性会使Js文件在下载完成后立即执行。 - 解析文档的时候遇到需要加载外部资源例如图片时,先解析这个节点,根据
src创建加载线程,异步加载图片资源,不阻塞解析文档,当然浏览器对于一个域名能够开启最大的线程数量会有限制。 - 文档解析完成,
document.readyState = "interactive"。 - 设置为
defer属性的<script>脚本开始按照顺序执行。 - 触发
DOMContentLoaded事件。 - 等待设置为
async属性的<script>以及图片与<iframe>等加载,直至页面完全加载完成。 load事件触发,document.readyState = "complete"。
调用
有些时候我们希望尽快介入对DOM的干涉,此时调用DOMContentLoaded事件显然更加合适,而为了处理各种浏览器,需要对其进行兼容处理。
- 对于支持
DOMContentLoaded的浏览器使用DOMContentLoaded事件。 - 如果是小于
525版本的Webkit则通过轮询document.readyState来实现。 - 对于旧版本的
IE浏览器使用Diego Perini发现的著名hack。
/* https://www.cnblogs.com/JulyZhang/archive/2011/02/12/1952484.html */
/*
* 注册浏览器的DOMContentLoaded事件
* @param { Function } onready [必填]在DOMContentLoaded事件触发时需要执行的函数
* @param { Object } config [可选]配置项
*/
function onDOMContentLoaded(onready, config) {
//浏览器检测相关对象,在此为节省代码未实现,实际使用时需要实现。
//var Browser = {};
//设置是否在FF下使用DOMContentLoaded(在FF2下的特定场景有Bug)
this.conf = {
enableMozDOMReady: true
};
if (config)
for (var p in config)
this.conf[p] = config[p];
var isReady = false;
function doReady() {
if (isReady) return;
//确保onready只执行一次
isReady = true;
onready();
}
/*IE*/
if (Browser.ie) {
(function() {
if (isReady) return;
try {
document.documentElement.doScroll("left");
} catch (error) {
setTimeout(arguments.callee, 0);
return;
}
doReady();
})();
window.attachEvent('onload', doReady);
}
/*Webkit*/
else if (Browser.webkit && Browser.version < 525) {
(function() {
if (isReady) return;
if (/loaded|complete/.test(document.readyState))
doReady();
else
setTimeout(arguments.callee, 0);
})();
window.addEventListener('load', doReady, false);
}
/*FF Opera 高版webkit 其他*/
else {
if (!Browser.ff || Browser.version != 2 || this.conf.enableMozDOMReady)
document.addEventListener("DOMContentLoaded", function() {
document.removeEventListener("DOMContentLoaded", arguments.callee, false);
doReady();
}, false);
window.addEventListener('load', doReady, false);
}
}
每日一题
https://github.com/WindrunnerMax/EveryDay
参考
https://juejin.im/post/6844903667733118983
https://juejin.im/post/6844903535314731021
https://juejin.im/post/6844903623583891469
https://juejin.im/post/6844904072340832264
https://juejin.im/post/6844904176569286669
https://www.cnblogs.com/caizhenbo/p/6679478.html
https://www.cnblogs.com/rubylouvre/p/4536334.html
https://developer.mozilla.org/zh-CN/docs/Web/Events/DOMContentLoaded
https://gwjacqueline.github.io/%E5%BC%82%E6%AD%A5%E5%8A%A0%E8%BD%BDjs/
domReady的理解的更多相关文章
- 谈谈DOMContentLoaded:Javascript中的domReady引入机制
一.扯淡部分 回想当年,在摆脱写页面时js全靠从各种DEMO中copy出来然后东拼西凑的幽暗岁月之后,毅然决然地打算放弃这种处处“拿来主义”的不正之风,然后开启通往高大上的“前端攻城狮”的飞升之旅.想 ...
- 第二课:判断js变量的类型以及domReady的原理
1.类型的判断: js五种简单数据类型有:null,undefined,boolean,number,string. 还有复杂的数据类型:Object,Function,RegExp,Date,自定义 ...
- 深入理解Javascript封装DOMContentLoaded事件
最近在写一个Javascript的框架,刚把DOMContentLoaded事件封装好,略带小兴奋,把开发过程中遇到的原理和兼容性问题做篇笔记,省的忘记到处找. 我们在写js代码的时候,一般都会添加w ...
- 理解CSS视觉格式化
前面的话 CSS视觉格式化这个词可能比较陌生,但说起盒模型可能就恍然大悟了.实际上,盒模型只是CSS视觉格式化的一部分.视觉格式化分为块级和行内两种处理方式.理解视觉格式化,可以确定得到的效果是应 ...
- 彻底理解AC多模式匹配算法
(本文尤其适合遍览网上的讲解而仍百思不得姐的同学) 一.原理 AC自动机首先将模式组记录为Trie字典树的形式,以节点表示不同状态,边上标以字母表中的字符,表示状态的转移.根节点状态记为0状态,表示起 ...
- 理解加密算法(三)——创建CA机构,签发证书并开始TLS通信
接理解加密算法(一)--加密算法分类.理解加密算法(二)--TLS/SSL 1 不安全的TCP通信 普通的TCP通信数据是明文传输的,所以存在数据泄露和被篡改的风险,我们可以写一段测试代码试验一下. ...
- node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理
一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...
- 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念
一.前言 DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了.自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平 ...
- 学习AOP之透过Spring的Ioc理解Advisor
花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...
随机推荐
- 计算机网络-链路层(4)WiFi:802. 11无线LAN
有几套有关无线LAN 的802. 11标准,包括802.11b.802.11a和802.11g. 802.11g是至今为止最为流行的技术.一些双模式(802.11a/g)和三模式(802.11a/b/ ...
- muduo源码解析7-countdownlatch类
countdownlatch class countdownlatch:noncopyable { }; 作用: countdownlatch和mutex,condition一样,用于线程之间的同步, ...
- 微信商户H5支付申请不通过被驳回解法,拒绝提示:网站有不实内容或不安全信息
H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付.主要用于触屏版的手机浏览器请求微信支付的场景.可以方便从外部浏览器唤起 ...
- 快速构建一个完整的Selenium框架
今天跟大家细讲如何构建一个完整的selenium框架,当你学会了这一篇你就也可以说自己会selenium自动化测试了. 1.新建项目,结构如图: 注意:整个项目除了最外层的是文件夹,其他的都是包(pa ...
- Jigsaw pre-training:摆脱ImageNet,拼图式主干网络预训练方法 | ECCV 2020
Jigsaw pre-training以拼图的方式从检测数据集中生成用于主干网络预训练的数据集,而不需要额外的预训练数据集,如ImageNet.另外为了让网络更好的适应拼图数据,论文提出ERF-ada ...
- 记一些Python(Pymysql)建表、增删改查等基础操作(小白适用)
1.读取sql文件创建数据表 有一个形如下图的sql文件,使用python读取文件并在数据库中创建所有的表. 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道 ...
- Database4.exe用来导入excel
从ACCESS数据库导出的EXCEL表格,可以通过database4.exe来连接,并导出sql脚本,再用database4.exe来连接ACCESS并先创建于脚本结构一致的表,然后复制脚本,从新生成 ...
- 寻找链表的倒数第k个节点
寻找链表的倒数第k个节点 题目:已知一个带有表头结点的单链表,节点结构为(data,next),假设该链表只给出了头指针list.在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个 ...
- KMP - NOI2014 动物园
单题分析:NOI2014 动物园. 题目分析:很明显题目已明确指出这是有关KMP的题,思考KMP.本题与普通KMP不同之处在于它求的是不相交最长相同前缀后缀. 如何处理不相交: 1.暴力 2. ...
- C#知识点:操作XML
XML是什么就不用说了文本标记语言. 主要纪录如何对XML文件进行增删改查. Xml的操作类都存在System.xml命名空间下面. 应用型的直接上代码 using System; using Sys ...