从浏览器渲染过程看重绘回流基础教程_渲染基础知识

渲染过程浏览器渲染过程如下:解析 HTML,生成 DOM 树,解析 CSS,生成 CSSOM 树。将 DOM 树和 CSSOM 树结合,生成渲染树(Render Tree)。Layout(回流): 根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)。Painting(重绘): 根据渲染树以及回流得到的几何信息,得到节点的绝对像素。D

从浏览器渲染过程看重绘回流基础教程

渲染过程

从浏览器渲染过程看重绘回流基础教程_渲染基础知识

从浏览器渲染过程看重绘回流基础教程_渲染基础知识

浏览器渲染过程如下:

  1. 解析 HTML,生成 DOM 树,解析 CSS,生成 CSSOM 树。
  2. 将 DOM 树和 CSSOM 树结合,生成渲染树(Render Tree)。
  3. Layout(回流): 根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)。
  4. Painting(重绘): 根据渲染树以及回流得到的几何信息,得到节点的绝对像素。
  5. Display: 将像素渲染到屏幕上。

阻塞问题:

  1. 构建 CSSOM 会阻塞浏览器渲染,但不会阻塞解析 HTML 构建 DOM树。

  2. JavaScript 会阻塞 DOM 树构建。

    当 HTML 解析器遇到一个 script 标签时,它会暂停构建 DOM,将控制权移交给 JavaScript 引擎;等 JavaScript 引擎运行完毕,浏览器会从中断的地方恢复 DOM 构建。

  3. JavaScript 可以查询和修改 DOM 与 CSSOM,会导致竞态问题。

    浏览器尚未完成 CSSOM 的下载和构建,而我们却想在此时运行 JavaScript,会怎样?答案很简单,对性能不利:浏览器将延迟执行 JavaScript 和 DOM 构建,直至其完成 CSSOM 的下载和构建。

异步脚本

从浏览器渲染过程看重绘回流基础教程_渲染基础知识

  1. 携带 defer属性的脚本,顺序执行,会在DOMContentLoaded 事件触发之前执行。

    标准里defer是顺序执行,但因为浏览器可能并未按照标准实现,所以现实情况不一定是顺序执行。

  2. 携带 async属性的脚本,乱序执行,会在loaded 事件触发之前执行。

像素管道(pixel pipeline)

浏览器 60 帧刷新率中的每一帧,像素至屏幕管道中的关键点可以分为 5 个步骤。

从浏览器渲染过程看重绘回流基础教程_渲染基础知识

  • JavaScript: JavaScript 修改 DOM 和 CSS。比如用 JavaScript 实现动画。
  • 样式计算:根据匹配选择器(例如 .headline 或 .nav > .nav__item)计算出元素的 CSS 规则并计算每个元素的最终样式。
  • 布局(回流):浏览器开始计算元素要占据的空间大小及其在屏幕的位置。网页的布局模式意味着一个元素可能影响其他元素,例如 <body> 元素的宽度一般会影响其子元素的宽度以及树中各处的节点。
  • 绘制(重绘):绘制是填充像素的过程。它涉及绘出文本、颜色、图像、边框和阴影,基本上包括元素的每个可视部分。绘制一般是在多个表面(通常称为层)上完成的。
  • 合成:由于页面的各部分可能被绘制到多层,由此它们需要按正确顺序绘制到屏幕上,以便正确渲染页面。对于与另一元素重叠的元素来说,这点特别重要,因为一个错误可能使一个元素错误地出现在另一个元素的上层。

跳过 Layout 和 Paint

更改一个既不要布局也不要绘制的属性,则浏览器将跳过 Layout 和 Paint,只执行 Composite。

跳过 Layout

如果只修改 paint only 属性(例如背景图片、文字颜色或阴影等),即不会影响页面布局的属性,浏览器会跳过 Layout 过程,但仍将执行 Paint。

这个过程就是浏览器重绘。

无跳过

如果修改元素的 layout 属性,也就是改变了元素的几何属性(例如宽度、高度、左侧或顶部位置等),浏览器会检查所有其他元素,然后自动重排页面。任何受影响的部分都需要重新绘制,而且最终绘制的元素需会进行合成。

这个过程就是触发回流和重绘。

通过上面的描述可以知道,触发重绘不一定会触发回流,但触发回流一定会触发重绘。

浏览器优化

浏览器为了避免在一帧的时间里频繁的触发回流和重绘过程,会将多次回流、重绘汇总成一次进行处理。一般是将回流、重绘操作推入一个队列中,直到队列达到阈值或者需要执行时,才会清空队列。

强制回流

执行获取布局信息的操作,为了获取正确的数据,浏览器会清空队列,触发回流重绘。

读取以下属性或者使用以下方法会导致强制回流:

  • offsetTop、offsetLeft、offsetWidth、offsetHeight
  • scrollTop、scrollLeft、scrollWidth、scrollHeight
  • clientTop、clientLeft、clientWidth、clientHeight
  • getComputedStyle()
  • getBoundingClientRect()

减少回流重绘

避免强制回流

对于频繁读取布局信息的操作,可以使用requestAnimationFrame(),将操作汇集起来并延迟入队,因为requestAnimationFrame()是在每一帧重绘前执行的。

具体查看MDN_requestAnimationFrame

或者将值缓存起来也是可以的。

// 频繁读取布局信息会导致强制回流
for (let i = 0; i < arr.length; i++) {
  arr[i].style.padding = el.style.clientWidth + '5px';
  // do something
}
  
// 缓存
let width = el.style.clientWidth;
for (let i = 0; i < arr.length; i++) {
  arr[i].style.padding = width + '5px';
  // do something
}

脱离文档流

对于会频繁修改属性的元素,可以使其脱离文档流,这样可以最小化回流和重绘。因为脱离了文档流,修改不会影响文档流整体。

  1. 设置 display 为 none
  2. 设置 position 为 absolute、fixed

GPU 加速绘制,提升为合成层

所有的元素会在 Composite 进行渲染层合并,即形成层叠上下文的元素会渲染在不同的渲染层中。

但一个渲染层满足以下条件会被提升为合成层,由硬件加速绘制:

  • 3D transform: translate3d、translateZ
  • video、canvas、iframe 等元素
  • will-change

对于动画可以使用 transform 和 opacity 属性,会跳过上面五个步骤中的Layout、Paint,不触发回流重绘,但动画的其它属性,比如 background-color 这些,还是会引起回流重绘。

海计划公众号
(0)
上一篇 2020/03/20 06:49
下一篇 2020/03/20 06:49

您可能感兴趣的内容

  • 聊聊鉴权那些事基础指南_权限菜鸟教程下载

    在系统级项目开发时常常会遇到一个问题就是鉴权,身为一个前端来说可能我们距离鉴权可能比较远,一般来说我们也只是去应用,并没有对权限这一部分进行深入的理解。什么是鉴权鉴权:是指验证用户是否拥有访问系统的权利。传统的鉴权是通过密码来验证的。这种方式的前提是,每个获得密码的用户都已经被授权。在建立用户时,就为此用户分配一个密码,用户的密码可以由管理员指定,也可以由用

    2020/03/26
  • 畅游视觉设计中心基础入门_用爱去释放奇妙的设计魔法,描绘让你我感动的虚拟人生

    畅游视觉设计中心基础知识教程 官方网址:http://vc.changyou.com/ 简介描述:用爱去释放奇妙的设计魔法,描绘让你我感动的虚拟人生 搜狐畅游视觉设计中心团队。我们…

    2020/03/06
  • 一个十年老前端的感悟入门攻略_前端基础教程

    2009,我毕业了2009年,也就是在2008年金融危机后的一年,我于一所上海211数学系毕业了。这一年的招聘大环境并不好,我和几个同学都在临近毕业的时候参加了几个校内校外的招聘会。我本科学的是数学,那个时候不像现在,人工智能,大数据的岗位铺天盖地,薪酬诱人。应该说那时候还是互联网行业真正起飞的起点.我在一番折腾后进入了一个大概10来个人的左右,管理层由家庭

    2020/03/30
  • 基于 HTML5 Canvas 的交互式地铁线路图入门攻略_html小白知识

    前言前两天在 echarts 上寻找灵感的时候,看到了很多有关地图类似的例子,地图定位等等,但是好像就是没有地铁线路图,就自己花了一些时间捣鼓出来了这个交互式地铁线路图的 Demo,地铁线路上的点是在网上随便下载了一个,这篇文章记录自己的一些收获(毕竟我还是个菜鸟)以及代码的实现,希望能够帮到一些朋友。当然,如果有什么意见的可以直接跟我说,大家一起交流才会进

    2020/04/05
  • js 数组操作整理指南教程_数组基础指南

    基本操作增和改var a= new Array(); //创建一个数组
    a[0]=1;//直接指定修改
    a.push(1); //直接在最后新增一个删//arrayObj.splice(deletePos,deleteCount); //删除从指定位置deletePos开始的指定数量deleteCount的元素,数组形式返回所移除的元素a.splice[0,

    2020/03/20
  • 13款免费的API设计、开发和测试工具基础入门_工具菜鸟指南

    充分利用REST的API大行其道,用于创建、测试和管理这种API的工具也方兴未艾。无论你是API新手还是在赶进度的专家,都可以获得诸多服务,帮助API从概念阶段进入到生产阶段,许多服务不用花一分钱。以下是处理API​​的几项免费服务。一些是简易的应用程序,可简化组装或测试API的任务。另一些是完整的专业API管理服务的入门版,让你可以先试用一下;若有需要,可

    2020/03/26
  • Erlang 之父去世,他留给程序员两点忠告教程视频_程序员入门知识

    北京时间 4月20日,据Erlang Solutions、Erlang Factories的创始人Francesco Cesarini的推特称,Erlang之父Joe Armstrong于4月20日去世,享年68岁。Francesco怀念道:“尽管他不在了,但他的工作已经打下的基础,将对未来几代人都有用的。”Joe Armstrong 是谁?1950年12月

    2020/03/30
  • HTML5常用API基础知识教程_api使用攻略

    页面可见性API——Page Visibility
    API全屏API——Full Screen
    访问摄像头和麦克风——getUserMedia API
    电池API——Battery API
    预加载——Link Prefetching
    监听屏幕旋转变化接口: ——orientationchange
    手机震动: ——window.navigator.vibrat

    2020/03/22
  • 移动端开发touch和click的区别入门基础知识_区别小白知识

    1、click事件主要存在300毫秒的延迟,且不会存在穿透事件300ms的由来:这要追溯至 2007 年初。苹果公司在发布首款 iPhone 前夕,遇到一个问题:当时的网站都是为大屏幕设备所设计的。于是苹果的工程师们做了一些约定,应对 iPhone 这种小屏幕浏览桌面端站点的问题。这当中最出名的,当属双击缩放(double tap to zoom),这也是会

    2020/03/23
  • prerender小白知识_一个兼容多种不同平台(包括Node,PHP和Ruby)的一个服务

    prerender小白知识 官方网址:https://prerender.io/ GitHub:https://github.com/prerender/prerender 简介描…

    2020/03/06
  • Croppie.js基础知识入门图片裁剪, 压缩, 上传, 预览的js插件

    Croppie.js使用攻略 官方网址:http://foliotek.github.io/Croppie GitHub:https://github.com/Foliotek/C…

    2020/03/06
  • Less导入指令小白帮助_指令使用帮助

    在标准CSS中,@import 规则必须位于所有其他类型的规则之前。但是Less.js不在乎我们将 @import 语句放在什么位置。@import 伪指令常用于在代码中导入文件,它将Less 代码分布在不同的文件上,并允许轻松地维护代码的结构,我们可以将 @import 语句放在代码的任何位置。件扩展名@import 取决于文件扩展名,Less可以对语句进

    2020/03/26
  • 7 个开放式的 CSS 面试题及回答策略使用攻略_面试小白知识

    不管你是面试官还是求职者,里面的思路都能让你获益匪浅。你用 CSS 多久了?解析:这个问题可以让面试官了解求职者使用 CSS 的经验。它还可以告诉面试官该人是否将该技能作为业余爱好或在学术或专业环境中学习。面试官想知道些什么:求职者使用 CSS 的经验对创建网站的兴趣是否持续关注新技术参考答案:我在高中时就开始用 CSS 了。当时我和一些朋友为我们喜欢的电视

    2020/03/31
  • Angular有哪些版本?基础入门_angular小白攻略

    目前Angular有7个版本,分别为:AngularJS、Angular2、Angular4、Angular5、Angular6、Angular7、Angular8。下面本篇文章就来给大家介绍一下,希望对大家有所帮助。版本1AngularJS是一款由Google维护的开源JavaScript库,用来协助单一页面应用程序运行。它的目标是透过MVC模式(MVC)

    2020/03/22
  • ale.js零基础入门_一套用于以组件的形式构建用户界面的渐进式框架

    ale.js零基础入门 官方网址:https://www.alejs.org GitHub:https://github.com/Ale-js/ale 简介描述:一套用于以组件的形…

    2020/03/06
  • css选择器中:first-child与:first-of-type小白知识_选择器入门指南

    css选择器中:first-child与:first-of-type是比较容易混淆的概念,这里用案例介绍它们具体的区别。:first-child 选择器是css2中定义的选择器,从字面意思上来看也很好理解,就是第一个子元素。比如有段代码:

    第一个子元素

    第二个子元素

    第三个子元素
    <span

    2020/03/20