重排&重绘

1.重排:顾名思义表示页面进行了重新排布。浏览器是根据dom tree以及cssom tree合成的渲染树进一步进行页面绘制,所以当元素更改了几何属性时会导致之前构建的cssom树等失效,此时需要重新计算并排布;

2.重绘:浏览器对相应元素进行了重新绘制,如对宽高、颜色、border等进行重新设置时会触发;

老生常谈,重排一定会引起重绘。重绘不一定会伴有重排(修改背景色等);

导致重排的操作

1.添加或者删除可见的DOM元素
2.元素位置改变
3.元素尺寸改变
4.页面渲染初始化
5.浏览器窗口尺寸改变

每次改变大小等几何属性,浏览器都会重新进行渲染么?

举个例子

var ele = document.getElementById('myDiv');
ele.style.borderRight = '1px';
ele.style.borderRight = '2px';
ele.style.borderRight = '3px';
ele.style.borderRight = '4px';

如上所示↑。其实想想就知道浏览器肯定会对其进行合并渲染来提高性能;但是如果我们在中间需要对其属性进行获取,浏览器为了返回给你正确信息,就需要立刻进行渲染;

var ele = document.getElementById('myDiv');
ele.style.borderRight = '1px';
ele.style.borderRight = '2px';
ele.style.borderRight = '3px';
// 这里获取offsetTop属性
ele.style.borderRight = '4px';

因为offsetHeight属性需要返回最新的布局信息,因此浏览器不得不执行渲染队列中的“待处理变化”并触发重排以返回正确的值,所以上面的代码,前三次的操作会缓存在渲染队列中待处理,但是一旦offsetTop属性被请求了,队列就会立即执行,所以总共有两次重排与重绘。所以尽量不要在布局信息改变时做查询!!

Document.createDocumentFragment()

介绍一个api,Document.createDocumentFragment()

DocumentFragments are DOM Node objects which are never part of the main DOM tree. The usual use case is to create the document fragment, append elements to the document fragment and then append the document fragment to the DOM tree. In the DOM tree, the document fragment is replaced by all its children.

Since the document fragment is in memory and not part of the main DOM tree, appending children to it does not cause page reflow (computation of element's position and geometry). Historically, using document fragments could result in better performance.

当我们一定要在循环的过程中频繁创建并插入节点时,可以先创建一个fragment节点用来暂时存储,之后一次性插入;因为fragment节点是没有parentnode的,也不会出现在dom树中;当把它插入dom时插入的其实是他的所有子节点;这样只会在插入dom时才会触发一次渲染

var element  = document.getElementById('ul'); // assuming ul exists
var fragment = document.createDocumentFragment();
var browsers = ['Firefox', 'Chrome', 'Opera',
    'Safari', 'Internet Explorer'];

browsers.forEach(function(browser) {
    var li = document.createElement('li');
    li.textContent = browser;
    fragment.appendChild(li);
});

element.appendChild(fragment);

总结

重排和重绘是DOM编程中耗能的主要原因之一,平时涉及DOM编程时可以参考以下几点:

  1. 尽量不要在布局信息改变时做样式位置的查询;
  2. 同一个DOM的多个属性改变合并执行
  3. 如果要批量添加DOM,可以将其隐藏,插入后展示,这样只会触发一次重排(或者用Document.createDocumentFragment()也只会触发一次重新渲染)
  4. 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。

你可能感兴趣的:(重排&重绘)