zoukankan      html  css  js  c++  java
  • 浏览器渲染逻辑和重绘、回流解析

    浏览器从输入url 到 渲染出界面 中间经历的过程

    1 DNS 查询

    2 TCP 连接

    3 HTTP 请求即响应

    4 服务器响应

    5 客户端渲染

    浏览器是如何渲染UI的?(客户端的渲染)

    1 浏览器接收到 html 和 css 文件 ,并对html进行解析,生成 DOM 树 (遇到link,script 会造成阻塞)

    2 同时对css进行解析,生成 CSSOM 树

    3 将DOM树 和 CSSOM树 合成 Render 树(渲染树)

    4 根据渲染树来布局,以计算每个节点的几何信息。(定位坐标和大小,是否换行,各种position, overflow, z-index属性)

    5 调用GPU进行绘图,遍历render tree的每个节点,将元素显示到屏幕上

    css的加载和解析不会阻塞html文档的解析
    css的解析会阻塞js的执行,必须等到CSSOM生成后才能执行js
    js的执行会阻塞html文档的解析
    html一边解析一边显示
    css必须完全解析完毕才能进入生成渲染树环节

    重绘

    Repaint——屏幕的一部分要重画,比如某个CSS的背景色变了。但是元素的几何尺寸没有变。

    回流、重排

    Reflow——意味着元件的几何尺寸变了,我们需要重新验证并计算Render Tree。是Render Tree的一部分或全部发生了变化。这就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的几何尺寸发生了变化,需要重新布局,也就叫reflow)reflow 会从这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置,在reflow过程中,可能会增加一些frame,比如一个文本字符串必需被包装起来。

    回流的原因:
    1 Initial。网页初始化的时候。

    2 Incremental。一些Javascript在操作DOM Tree时。

    3 Resize。其些元件的尺寸变了。

    4 StyleChange。如果CSS的属性发生变化了。

    5 Dirty。几个Incremental的reflow发生在同一个frame的子树上。

    注: 一般来说,浏览器会把这样的操作积攒一批,然后做一次reflow,这又叫异步reflow或增量异步reflow。但是有些情况浏览器是不会这么做的,比如:resize窗口,改变了页面默认的字体,等。对于这些操作,浏览器会马上进行reflow。

    link 标签会阻塞html的解析
    script 标签会阻塞html的解析
    由于 DOM树和CSSOM才能生出渲染树,所以 css越早提供越好,一般推荐link标签写到head中,script 标签写到文档底部
    script标签异步加载 defer 、 async属性,不会影响DOM树的构建

    阻塞问题
    script标签会阻塞DOM树的构建
    CSSOM 的构建会阻塞 script标签中js的执行 (假如浏览器发现js中)

    defer
    <script src="app1.js" defer></script>
    <script src="app2.js" defer></script>
    <script src="app3.js" defer></script>
    

    defer 属性表示延迟执行引入的 JavaScript,即这段 JavaScript 加载时 HTML 并未停止解析,这两个过程是并行的。整个 document 解析完毕且 defer-script 也加载完成之后(这两件事情的顺序无关),会执行所有由 defer-script 加载的 JavaScript 代码,然后触发 DOMContentLoaded 事件。

    defer 不会改变 script 中代码的执行顺序,示例代码会按照 1、2、3 的顺序执行。所以,defer 与相比普通 script,有两点区别:载入 JavaScript 文件时不阻塞 HTML 的解析,执行阶段被放到 HTML 标签解析完成之后。

    async
    <script src="app.js" async></script>
    <script src="ad.js" async></script>
    <script src="statistics.js" async></script>
    

    async 属性表示异步执行引入的 JavaScript,与 defer 的区别在于,如果已经加载好,就会开始执行——无论此刻是 HTML 解析阶段还是 DOMContentLoaded 触发之后。需要注意的是,这种方式加载的 JavaScript 依然会阻塞 load 事件。换句话说,async-script 可能在 DOMContentLoaded 触发之前或之后执行,但一定在 load 触发之前执行。

    从上一段也能推出,多个 async-script 的执行顺序是不确定的。值得注意的是,向 document 动态添加 script 标签时,async 属性默认是 true

  • 相关阅读:
    3n+1问题
    判断x的m次方和y的m次方末尾三位数是否相等
    OpenJudge 计算概论1007:点评赛车
    整数划分问题【转】
    证明:平面内有5个整点,必有两个点连线的中点为整点【本资源整理自网络】
    欧几里德算法的证明
    导出本地和远程SVN项目, Export remote SVN repository
    Centos7的firewalld配置
    ESXi5.5下的Centos7虚机配置静态IP
    Dubbo消费端错误: ClassNotFoundException: org.apache.zookeeper.proto.WatcherEvent
  • 原文地址:https://www.cnblogs.com/honkerzh/p/13814839.html
Copyright © 2011-2022 走看看