时间线
时间线:浏览器开始加载页面的那一刻到这个页面完全加载完毕这个过程中 按顺序发生的每一件事情的总流程
1.document对象 js就起作用了
2.解析文档:从html文档写的第一行东西开始浏览器会从第一行阅读到最后一行 这个过程在传统浏览器种只是在阅读
解析文档的同时会构建DOM树同时进行3构建CSSOM document.readyState = ‘loading’ 加载中
3.遇到link js引擎开新的线程异步加载css外部文件 遇到style 构建CSSOM
4.如果没有设置异步加载的script 阻塞文档解析 等待js脚本加载并且执行完成后 继续解析文档
5.如果有异步加载的script 异步加载js脚本 不阻塞解析文档 (但是异步脚本中不能使用document.write())
6.解析文档如果遇到img 先解析这个节点 只要写了src 就会创建加载线程 异步加载图片资源 不阻塞解析文档
7.文档解析完成 document.readyState = ‘interactive’ 解析完成
8. 如果设置defer script js脚本开始按照顺序执行 defer要在文档解析完成后执行
9. 文档解析完成后 会触发DOMContentLoaded事件 监听这个事件就知道文档什么时候解析完 文档解析完不代表资源加载完 这个事件触发后 同步的脚本执行阶段就变成了事件驱动阶段
10.async script 加载并执行完毕 img等资源加载完毕 window对象种的onload事件才触发 document.readyState = ‘complete’ 加载完成
window.onload 与 DOMContentLoaded的区别
window.onload是在文档解析完成后并且全部js加载执行完毕 img等资源加载完毕后才会触发
DOMContentLoaded是在文档解析完成后就触发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style></style>
</head>
<body>
<div></div>
<script>
console.log(document.readyState);
document.onreadystatechange = function () {
console.log(document.readyState);
};
document.addEventListener(
'DOMContentLoaded',
function () {
console.log('DOMContentLoaded');
},
false
);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
width: 100px;
height: 100px;
background-color: #000;
}
</style>
</head>
<body>
<div></div>
<script src="./index.js" async="async"></script>
</body>
</html>
document.write('123');
当直接在script标签内使用document.write时创建的内容会在scirpt标签下添加
此时scirpt标签还没有构建完成 页面还没有开始渲染 此时正常追加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
width: 100px;
height: 100px;
background-color: #000;
}
</style>
</head>
<body>
<div></div>
<script>
document.write('<h1>abc</h1>');
</script>
</body>
</html>
window.onload 要等文档解析 并且DOM树CSS树渲染树构建完成 并且渲染完 并且资源(图片资源等src)加载完后才触发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
width: 100px;
height: 100px;
background-color: #000;
}
</style>
</head>
<body>
<div></div>
<script>
window.onload = function () {
document.write('<h1>abc</h1>');
};
</script>
</body>
</html>
封装 domReady
文档解析完毕函数
function domReady(fn) {
if (document.addEventListener) {
document.addEventListener(
'DOMContentLoaded',
function () {
document.removeEventListener('DOMContentLoaded', arguments.callee, false);
fn();
},
false
);
} else if (document.attachEvent) {//兼容ie
document.attachEvent('onreadystatechange', function () {
if (this.readyState === 'complete') {
document.attachEvent('onreadystatechange', arguments.callee);
fn();
}
});
}
// 兼容ie6,7 有一个doScroll api控制滚动条 ,文档没解析完会报错
if (document.documentElement.doScroll && typeof window.frameElement === 'undefined') {
try {
document.documentElement.doScroll('left');
} catch (error) {//一但报错就延迟 知道不报错
return setTimeout(arguments.callee, 20);
}
fn();
}
}