浏览器的渲染、重绘以及回流

浏览器渲染

浏览器拿到html后会按自上而下的顺序依次执行,遇到link标签和img标签时会发送新的请求。渲染过程如下:

  • 浏览器遍历html标签后生成dom树
  • css加载完成后生成cssom树
  • dom树和cssom树全部生成后一起生成render树
  • 浏览器开始计算元素位置
  • 将节点内容呈现出来

大多数浏览器请求js文件时会暂停渲染过程以防止js文件修改dom导致之前的渲染做无用功,所以一般将js文件写在body标签底部。但是有些浏览器会几乎同时加载css和不影响dom结构的js,等这些文件加载后再加载剩余js文件。

重绘以及回流

定义

重绘:对某个区域、对象的重新渲染表现

回流:对某个区域、对象进行重绘,根据条件影响到它的祖先对象进入重绘(并可能无限递归直到顶级祖先对象)

触发

重绘如何出现:改变对象的形状、坐标、表现以及内容都会引发该对象被重新渲染,这种现象即为重绘。

回流如何出现:当该对象即将重绘时,浏览器会根据条件判断该对象的重绘结果是否会依赖该对象的祖先元素。如果有则将该对象祖先元素也加入本次重绘。并一直向上寻找,直到条件不匹配。此现象即为回流。

最后总结:
1、重绘可能引发回流
2、回流必定引发重绘

引发重绘和回流的操作

  • 调整窗口大小
  • 改变字体
  • 增加或者移除样式表
  • 内容变化,比如用户在input框中输入文字
  • 激活 CSS 伪类,比如 :hover (IE 中为兄弟结点伪类的激活)
  • 操作 class 属性
  • 脚本操作 DOM
  • 计算 offsetWidth 和 offsetHeight 属性
  • 设置 style 属性的值

优化回流

浏览器本身的优化策略:浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会flush队列,进行一个批处理。这样就会让多次的回流、重绘变成一次回流重绘。但有时候我们写的一些代码可能会强制浏览器提前flush队列,这样浏览器的优化可能就起不到作用了。当你请求向浏览器请求一些 style信息的时候,就会让浏览器flush队列。

所以我们要减少对render tree的操作(合并多次多DOM和样式的修改),并减少对一些style信息的请求,尽量利用好浏览器的优化策略

  • 将多次改变样式属性的操作合并成一次操作。
  • 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
  • 在内存中多次操作节点,完成后再添加到文档中去。例如要异步获取表格数据,渲染到页面。可以先取得数据后在内存中构建整个表格的html片段,再一次性添加到文档中去,而不是循环添加每一行。
  • 由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂的操作时,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发2次重排。
  • 在需要经常取那些引起浏览器重排的属性值时,要缓存到变量。
  • 如果想设定元素的样式,通过改变元素的 class 名 (尽可能在 DOM 树的最末端)
  • 避免设置多项内联样式
  • 权衡动画的平滑和速度
  • 避免使用table布局
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容