回流和重绘引发思考——DocumentFragment、Vue(keep-alive)

文章参考

  1. document.createDocumentFragment()
  2. 详解回流和重绘及优化

问题描述

昨天同事培训Vue问了一个“回流”和“重绘”的问题,自己回答的是数据量过大导致浏览器渲染慢和卡顿的问题,Vue解决办法是使用虚拟DOM,缓存DOM组件,应该是没有给出准确答案,会后自己深入了解了一下“回流和重绘”的问题,做一个笔记,方便自己后续学习

什么是“回流和重绘”?

参考详解回流和重绘及优化
个人理解:

  1. 回流 —— 将DOM节点和CSS样式结合准确的计算出DOM节点的表现形式(位置、形状),计算的过程就是回流
  2. 重绘 —— 经过了回流计算之后,就了解到哪些DOM显示(如何显示)和不显示,将DOM显示到浏览器中的过程就是重绘

何时会发生回流重绘?

回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流,回流场景:

  1. 添加或删除可见的DOM元素
  2. 元素的位置发生变化
  3. 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
  4. 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
  5. 页面一开始渲染的时候(这肯定避免不了)
  6. 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)

回流一定会触发重绘,而重绘不一定会回流.

重绘引发的性能问题?

根据改变的范围和程度,渲染树中或大或小的部分需要重新计算,有些改变会触发整个页面的重排,比如,滚动条出现的时候或者修改了根节点。每次重排都会造成额外的计算消耗

如何减少重绘和回流
  1. 尽量一次修改完所有的样式属性
const el = document.getElementById('test');
el.style.padding = '5px';
el.style.borderLeft = '1px';
el.style.borderRight = '2px'

改为

const el = document.getElementById('test');
el.style.cssText += 'border-left: 1px; border-right: 2px;   padding: 5px;
  1. 批量修改Dom元素
    即使元素脱离文档流,在脱离文档流的元素中修改完成,然后最后一次插入到DOM文档流中

    有三种方式可以让DOM脱离文档流:

    • 隐藏元素,应用修改,重新显示
    • 使用文档片段(document fragment)在当前DOM之外构建一个子树,再把它拷贝回文档。
    • 将原始元素拷贝到一个脱离文档的节点中,修改节点后,再替换原始的元素。
  2. 避免触发同步布局事件

  3. 对于复杂动画效果,使用绝对定位让其脱离文档流

  4. css3硬件加速(GPU加速)

DocumentFragment是一个存在于内存的 DOM 片段,不属于当前文档

参考 document.createDocumentFragment()

document.createDocumentFragment方法生成一个空的文档片段对象(DocumentFragment实例)。

var docFragment = document.createDocumentFragment();
```因为DocumentFragment不属于当前文档,对它的任何改动,都不会引发网页的重新渲染,比直接修改当前文档的 DOM 有更好的性能表现。

```js
var docfrag = document.createDocumentFragment();

[1, 2, 3, 4].forEach(function (e) {
  var li = document.createElement('li');
  li.textContent = e;
  docfrag.appendChild(li);
});

var element  = document.getElementById('ul');
element.appendChild(docfrag);

Vue keep-alive 引发的思考

参考 在动态组件上使用 keep-alive

  1. keep-alive 组件的作用
    组件实例能够被在它们第一次被创建的时候缓存下来
  2. 属性
    include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
    exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
    max - 数字。最多可以缓存多少组件实例。

个人猜想:

  1. Vue组件是一个对象,包含了 HTML 部分(即DOM)
  2. 当使用Router切换组件的时候,就把当前的组件没有销毁,只是让HTML脱离了文档流,缓存到内存中,然后创建一个新的Vue对象,把新的Vue对象的template内容挂载到DOM中(文档流中),显示出来
  3. 当切换回来的时候,去缓存中查找,是否之前有组件,如果有,就使用之前缓存的,把Vue对象的template重新挂载到DOM中(文档流),提高效率,这个也是虚拟DOM的原理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值