用户从地址栏输入网址按下回车到页面展示出来 整个过程发生了什么 ?
浏览器加载一份html文档是怎么加载的?
1.把标签 文本 注释 属性等等 解析为节点树(DOM Tree)
2.解析DOMtree中的节点时遇到了不同的元素会有不同的操作:
2.1.style标签或者link-css 遇到css代码 就会把css代码解析为CSS样式结构体
2.2 遇到了src 会去加载(网络请求)资源
3.把2.1CSS样式结构体和1DOM Tree结合变成呈现树/渲染树(Render Tree)
4.按照Render Tree绘制页面
如何绘制页面:渲染树生成后,还是没有办法渲染到屏幕上,渲染到屏幕需要得到各个节点的位置信息,这就需要布局(Layout)的处理了。
布局阶段会从渲染树的根节点开始遍历,由于渲染树的每个节点都是一个Render Object对象,包含宽高,位置,背景色等样式信息。所以浏览器就可以通过这些样式信息来确定每个节点对象在页面上的确切大小和位置,布局阶段的输出就是我们常说的盒子模型,它会精确地捕获每个元素在屏幕内的确切位置与大小。需要注意的是:
像是浮动,固定定位,都会脱离文档流,其实就是脱离Render Tree。
在绘制阶段,浏览器会遍历渲染树,调用渲染器的paint()方法在屏幕上显示其内容。渲染树的绘制工作是由浏览器的UI后端组件完成的。
然后就是重绘和回档
回档:当render tree中因为元素的数量,尺寸,布局,隐藏等改变而需要重新构建。这就称为回流或者回档(其实我觉得叫重新布局更简单明了些)。每个页面至少需要一次回流,就是在页面第一次加载的时候。
重绘:当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
关系:重绘不一定会回档,但是回档一定会重绘。
但是大量的重绘和回档同样也导致了问题:
频繁的重绘/回流会造成页面性能不好==>页面卡顿 迟缓 手机发烫
因此操作页面时: 尽量避免高频重绘 使用框架
案例:假如我们现在要创建一个100X100的表格里面全部放满了内弄
let tb=document.querySelector(".box")
for(let i=0;i<100;i++){
let tr=document.createElement("tr")
tb.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)
}
}
重绘/回档了10100次,100个tr,每个tr中又创建了100个td
那么我就介绍一个新的东西”冰“元素,先来看代码
let tb=document.querySelector("#box")
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)
fra1=document.createDocumentFragment()
这一行代码就创建了一个”冰“元素,他创建了在内存中,还没有添加到文档树中,所以没有重绘和回档,当把tr和td全部加进去之后,把这个”冰“元素添加到父元素中,”冰“就化了(容易理解的说法),冰元素不会添加到父元素中,但是他的子代会全部添加到父元素中
所以只回档了一次