这里只针对dom操作阶段——浏览器解析html文档
浏览器加载一份html文档是怎么加载的?
1.把标签 文本 注释 属性等等 解析为节点树(DOM Tree)
2.解析DOM tree中的节点时遇到了不同的元素会有不同的操作:
2.1.style标签或者link-css 遇到css代码 就会把css代码解析为CSS样式结构体
2.2 遇到了src 会去加载(网络请求)资源
3.把2.1CSS样式结构体和1DOM Tree结合变成呈现树/渲染树(Render Tree)
4.按照渲染树绘制页面(通过显卡把页面画到屏幕上)
图形说明:
在绘制页面会涉及到两个知识点:重绘和回流(又称回档)
重绘:当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
回流:当render tree中因为元素的数量,尺寸,布局,隐藏等改变而需要重新构建。这就称为回流或者回档(其实我觉得叫重新布局更简单明了些)。每个页面至少需要一次回流,就是在页面第一次加载的时候。
两者的关系:重绘不一定会引起回流,但是回流一定会引起重绘。
代码说明重绘和回流:
<style>
.box{
width: 200px;
height: 200px;
background-color: red;
}
</style>
<div class="box">box</div>
<script>
var box=document.querySelector(".box")
box.onclick=function(){
// box.style.visibility= "hidden";//重绘不回流
// box.style.display= "none";//回流
}
/*
解析:
visibility= "hidden"不会改变文档树的布局,只是将它透明,即只是外观改变
display= "none"而是将这个块级元素隐藏,文档树结构发生变化
*/
</script>
在操作页面时 频繁的重绘/回流会造成页面性能不好==>页面卡顿 迟缓 手机发烫
因此要尽量避免页面的重绘和回流,尤其是回流。
解决方案:
1、使用框架,框架的底层为我们设计了避免频繁的重绘/回流的程序
2、在DOM操作中,用document.createDocumentFragment()创建一个元素来承载即将渲染的元素,它在内存中还不在文档中。
代码展示:
<div id="box">
<table></table>
</div>
<script>
let tb=document.querySelector("table")
let fra1=document.createDocumentFragment()//它在内存中还不在文档中
for(let i=0;i<100;i++){
let tr=document.createElement("tr")
fra1.appendChild(tr)
for(let j=0;j<100;j++){
let dt=new Date().getTime()
let td=document.createElement("td")
td.innerHTML=dt
tr.appendChild(td)
}
}
tb.appendChild(fra1)//它自己不会添加到文档树中用于渲染
</script>
采用这个方法只会回流一次。
补充:不同的阶段用不同的承载:
dom=>fragment
wx=>block
vue=>template
react=></>