美文网首页
浏览器底层渲染机制和DOM的回流重绘

浏览器底层渲染机制和DOM的回流重绘

作者: 江平路 | 来源:发表于2020-08-29 20:18 被阅读0次

浏览器渲染过程

首先要从服务器获取需要渲染的内容,此时获取到的是文件流(进制编码内容),那么接下来浏览器会把16进制字节信息编译为代码字符串,然后按照W3C规则进行字符解析生成对应的tokens,再转换成浏览器内核可以识别渲染的DOM节点,最后再按照节点解析为对应的DOM树和CSSOM树。

image.png

1.加载并解析HTML

当用户输入url地址后,浏览器会先拿到html文件下载完并进行解析。

2.其他静态资源下载

html文件在解析过程中,如果发现html文本里,引入了一些外部资源链接,比如css、js和图片等,会立即启用别的线程下载这些静态资源。在<head> 标签中遇到js文件时,html的解析会被停下来,等js文件下载结束并执行完,html的解析才会继续,来防止js改变已解析的结果。

由以上可以知道,js文件放在<head>文件中,属于同步加载,会阻塞dom树的构建,进而影响页面的加载。当页面引入的js文件过多时,页面会出现长时间的白屏。
如何避免上面的问题呢?有以下三个解决方案。

1.<script>标签放在body标签里面(<body>之前)
由于dom是自上而下进行解析的,因此js不会阻塞dom的解析,而且这个时候可以在js中操作dom

2.设置defer属性
在<script>标签中设置defer属性,将脚本语言设置为延迟加载,当浏览器遇到带有defer属性的<script>标签时, 会再开启一个线程去下载js文件,同时继续解析html文件,等html全部解析完,dom加载完成后,再去加载下载好的js文件,只是用引入外部文件,并且可以确保所有加了 defer 属性的脚本会按顺序执行。

3.设置async属性
async属性和defer属性类似,也时开启一个线程去下载js文件,但和defer不同的是,async会在js文件加载完成后立即执行,而不是等到dom全部加载完成后再执行,所以还是有可能造成阻塞。同样的也是只是用外部引用脚本语言,如果有多个设置了async的文件,不能像defer那样按顺序执行。

4.动态创建脚本

<script>
var _html = _html || []
(function(){
    var hm = document.createElement("script")
    hm.src = "http://www.baidu.com/han.js"
    var s = document.getElementsByTageName('script')[0]
     s.parentNode.insertBefore(hm, s);
})()
</script>

3.dom树的构建

dom的全程,文档对象模型,在html解析时,解析器会把解析完的html转化成dom对象,再进一步的构建dom树

4.cssdom的构建

当css下载完成后,css解析器会对css进行解析,把css解析成css对象,然后把这些css对象组装成一颗cssdom树

5.渲染树的构成

dom和cssdom构建完成后,浏览器会根据这两颗树构建出渲染树

6.布局计算

渲染树构建完成以后,所有元素的位置关系和需要应用的样式就确定了。这时候浏览器会计算出所有元素的大小 和绝对位置

布局(Layout)或回流/重排(reflow)—— 计算元素在设备视口中的大小和位置;
绘制/重绘(painting)—— 根据渲染树以及回流得到的几何信息,得到节点的绝对像素;

7.渲染

布局计算完成以后,浏览器就可以在页面上渲染元素了,经过渲染引擎的处理后,整个页面就显示在了屏幕上

link、@import引入的区别

link和@import都是导入外部样式(服务器获取样式文件),区别如下:

//link
<link href="css/style.css" rel="stylesheet" type="text/css"></link>

//import
@import ...;
  • link——GUI渲染不会停止,浏览器会派发新的线程(HTTP线程)去加载资源文件,无论CSS是否请求回来,代码继续渲染;

  • @import——GUI渲染暂时停止渲染,去服务器加载资源文件,请求没有返回之前是不会继续渲染的;

  • 如果是嵌入式style,GUI直接渲染;

script标签中defer和async有什么区别

script会阻碍GUI渲染,先请求js(http线程),在把请求回来的执行,只有js执行完再去GUI渲染;

defer:GUI继续渲染,同时http去请求,请求回来也不会立即执行,而是等到GUI渲染完再去按照之前引入的script顺序依次执行。

async:GUI继续渲染,同时http去请求,当请求回来后立即先执行js,GUI暂停,js执行完之后GUI继续。谁先回来谁执行(适用于没有依赖顺序的)。

用图来说明一下更加容易理解:

image.png

性能优化(基于渲染机制优化)

1、减少DOM树渲染时间(HTML层级不要太深,标签语义化);
2、减少CSSOM树渲染时间(选择器从右向左解析,尽可能减少选择器层级);
3、减少HTTP请求次数和请求大小;
4、一般会把CSS放在页面的开始位置(提前请求资源,用link不用import,对于移动断如果css较少尽可能使用嵌入式);
5、避免白屏,可快速生成loading渲染树(前端骨架屏);
6、服务器的SSR骨架屏所提高的渲染是避免了客户端再次单独请求数据,而不是样式和结构上的首屏处理;
7、把JS放在页面底部以及尽可能使用defer或者async;
8、CRP性能节点优化;

预处理机制

预先把所有请求资源在GUI渲染之前就去发送请求,http并发限制(6-7);

回流(重排)和重绘

回流/重排——元素位置/大小/页面布局和几何信息变化,触发重新布局,导致渲染树重新计算布局和渲染,例:元素位置(移动)、尺寸(width/height/padding/margin/border)、内容发生变化等,页面一开始渲染时(无法避免,因为回流根据视口大小来计算元素位置和大小,浏览器窗口尺寸变化也会引发回流);

重绘——元素样式改变(宽高、大小、位置不变),eg:outline、color、background-color、visibility等;

回流比重绘更耗费性能。

注:回流一定会触发重绘,重绘不一定会回流。

box.onclick=function(){
    //这两行修改操作只引发一次回流
    box.style.width = "200px";
    box.style.height = "200px";
}

box.onclick=function(){
    //引发两次回流,因为一旦遇到获取样式的代码需要把之前队列中的样式进行渲染
    box.style.width = "200px";
    console.log(box.offsetWidth);
    box.style.height = "200px";
}
复制代码

浏览器渲染队列机制:遇到修改样式代码,浏览器没有立即渲染,而是先把它放到渲染队列中,继续看下面是否还是修改样式的,是的话继续放进去......直到遇到获取元素样式的代码或者没有修改样式的代码了,则立即把队列中的样式统一进行渲染,最后只引发一次回流重绘。

避免回流重绘:

  • ​ 分离读写(获取和修改分开);

    box.style.left = "200px";
    box.style.top = "200px";
    
    box.offsetLeft;
    box.offsetTop;
    
  • ​ 缓存布局;

    div.style.left = div.offsetLeft - 1 + 'px';
    =>
    //先获取值再使用
    var curLeft = div.offsetLeft;
    div.style.left = curLeft - 1 + 'px';
    
  • ​ 元素批量修改;

    let frg = document.createDocumentFragment();
    for(let i=0;i<10;i++){
        let span = document.cereateElement('span');
        span.innerHTML = i;
        frg.appendChild(i);
    }
    document.body.appendChild(frg);   //创建文档碎片,引发一次回流
    

相关文章

  • 22,重绘、回流

    1,浏览器渲染机制 2,重绘 3,回流 > 重绘。 4,浏览器优化 5,减少重绘和回流

  • 浏览器底层渲染机制和DOM的回流重绘

    浏览器渲染过程 首先要从服务器获取需要渲染的内容,此时获取到的是文件流(进制编码内容),那么接下来浏览器会把16进...

  • 2019-11-23

    浏览器渲染机制 url输入到显示 回流 重绘 白屏 或无样式闪烁

  • 你怎么也理解不了的回流和重绘

    浏览器的渲染过程 本文先从浏览器的渲染过程来从头到尾的讲解一下回流重绘,如果大家想直接看如何减少回流和重绘,优化性...

  • 回流和重绘(个人笔记)

    本文参考:你真的了解回流和重绘吗 浏览器的渲染过程 解析HTML,生成DOM树,解析CSS,生成CSSOM树 将D...

  • [ JS 进阶 ] Repaint 、Reflow 的基本认识和

    讲到 Repaint(重绘)和Reflow(回流)不得不提一下 浏览器的渲染机制,请看下图: 解析HTML标签,构...

  • 浏览器重绘和回流

    本文先从浏览器的渲染过程来从头到尾的讲解一下回流重绘,如果大家想直接看如何减少回流和重绘,可以跳到后面。(这个渲染...

  • 页面的回流,重绘

    页面的回流,重绘 浏览器渲染页面的处理流程 浏览器把获取到的HTML代码解析成1个DOM树,HTML中的每个tag...

  • 前端面试题总结

    1.请介绍下回流和重绘 回流:当我们对DOM的修改引起了DOM几何尺寸的变化(比如修改宽高和隐藏元素)时,浏览器需...

  • 浏览器渲染回流重绘与性能优化

    我们根据渲染的流程可知, 回流一定会触发重绘,而重绘不一定会回流。 渲染性能优化 回流和重绘的代价是比较昂贵的,渲...

网友评论

      本文标题:浏览器底层渲染机制和DOM的回流重绘

      本文链接:https://www.haomeiwen.com/subject/zhlqsktx.html