html解析过程与readyState
浏览器解析HTML是以从上到下,深度优先的顺序进行解析的
解析阶段:浏览器从上到下解析HTML,当浏览器解析完HTML时,会将readyState变更为interactive,触发DOMContentLoaded事件,开始进行渲染
渲染阶段:浏览器会等待css全部加载完毕,根据解析的DOM树与css进行渲染,当浏览器渲染完成,并且使用资源加载完成时,会将readyState变更为complete,触发onload事件
1.解析过程中若遇到link标签引入外部css,浏览器就会创建一个新线程加载外部资源,并继续解析HTML
该过程不会阻塞HTML的解析,但是会阻塞HTML的渲染,因为浏览器的渲染需要CSS的解析结果
2.解析过程中若遇到script标签
(1)script不是外部引入,且在link引入外部样式之前:解析到该标签时直接同步执行js代码,执行完再解析后面的内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
console.log('DOMContentLoaded')
})
document.onreadystatechange = () => {
console.log(document.readyState)
}
</script>
<script type="text/javascript">
console.log('1')
</script>
<script type="text/javascript">
console.log('2')
</script>
<link rel="stylesheet" type="text/css" href="http://192.168.12.121/m.css">
</head>
<body>
<div>1</div>
</body>
</html>
打印结果

(2)script不是外部引入,且在link引入外部样式之后:等待link标签加载完毕,并阻塞后面的HTML解析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
console.log('DOMContentLoaded')
})
document.onreadystatechange = () => {
console.log(document.readyState)
}
</script>
<script type="text/javascript">
console.log('1')
</script>
<link rel="stylesheet" type="text/css" href="http://192.168.12.121/m.css">
<script type="text/javascript">
console.log('2')
</script>
</head>
<body>
<div>1</div>
</body>
</html>
打印结果

(3)script为外部同步引入,且在link引入外部样式之前:等待该js文件加载,并阻塞后面的HTML解析,执行完该js后再继续解析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
console.log('DOMContentLoaded')
})
document.onreadystatechange = () => {
console.log(document.readyState)
}
</script>
<script src="http://192.168.12.121/m.js"></script>
<script type="text/javascript">
console.log('1')
</script>
<script type="text/javascript">
console.log('2')
</script>
<link rel="stylesheet" type="text/css" href="http://192.168.12.121/m.css">
</head>
<body>
<div>1</div>
</body>
</html>
打印结果

(4)script为外部同步引入,且在link引入外部样式之后:等待link标签、该js文件加载,并阻塞后面的HTML解析,执行完该JS后再继续解析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
console.log('DOMContentLoaded')
})
document.onreadystatechange = () => {
console.log(document.readyState)
}
</script>
<script type="text/javascript">
console.log('1')
</script>
<link rel="stylesheet" type="text/css" href="http://192.168.12.121/m.css">
<script src="./demo.js"></script>
</head>
<body>
<div>1</div>
</body>
</html>
打印结果

(5)script为外部异步引入:创建线程异步加载js,不会阻塞后面HTML的解析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
console.log('DOMContentLoaded')
})
document.onreadystatechange = () => {
console.log(document.readyState)
}
</script>
<script src="http://192.168.12.121/m1.js" async></script>
<script type="text/javascript">
console.log('1')
</script>
<link rel="stylesheet" type="text/css" href="http://192.168.12.121/m.css">
<script src="http://192.168.12.121/m2.js" async></script>
</head>
<body>
<div>1</div>
</body>
</html>
打印结果

script标签与link标签规律总结:
(1)同步script标签:会阻塞后面HTML的解析,等执行完该JS后才会继续解析
(2)异步script标签:不会阻塞HTML解析,也不会阻塞HTML渲染
(3)link标签会阻塞后面同步script标签的执行,并且会阻塞DOM渲染

浙公网安备 33010602011771号