part3:还是dom操作的优化

来源:互联网 发布:释迦牟尼为什么知乎 编辑:程序博客网 时间:2024/05/18 03:18

    开篇先让我们了解一下重排版(reflow)和重绘(repaint)。根据我的理解,发生重排版就一定会发生重绘。当页面中元素的width,height,margin,border,等属性发生改变时(也可以理解为大小,位置,形状,内容改变时),这些发生改变的元素和受这些改变影响的其他元素的几何属性会被浏览器重新计算,重构渲染树,这叫做重排版。然后浏览器重新绘制屏幕上受影响的部分,这叫重绘。当我们只改变元素的颜色时,只会发生重绘。另外,浏览器窗口大小改变,出现滚动条也会使浏览器对页面重排版。下面举一个优化的小例子:

var el = document.getElementById('mydiv');
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
el.style.padding = '5px';

  如果这样写,页面会进行三次重排版,效率低下。

//优化版

var el = document.getElementById('mydiv');
el.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';

这样就只要重排版一次


  在平时的项目中,我们可能会遇到这样的工作,在页面中的列表中插入一些行新的数据。如果不注意,我们可能会写出这样的代码:

//原始的列表

<ul id="mylist">
<li><a href="http://phpied.com">Stoyan</a></li>

<li><a href="http://julienlecomte.com">Julien</a></li>
</ul>

//要插入的数据

var data = [
{
"name": "Nicholas",
"url": "http://nczonline.net"
},
{
"name": "Ross",
"url": "http://techfoolery.com"
}
];

//进行插入的函数

function appendDataToElement(appendToElement, data) {
var a, li;
for (var i = 0, max = data.length; i < max; i++) {
a = document.createElement('a');
a.href = data[i].url;
a.appendChild(document.createTextNode(data[i].name));
li = document.createElement('li');
li.appendChild(a);
appendToElement.appendChild(li);

}
};

这样插入数据,每插一条都会引起一次重排版,如果插个几百条。。。。那我们如何解决呢。

思路一:我们可以让原始的列表隐藏(display:none),把他从文档中摘除,然后进行数据插入,最后再把整个列表放回文档

思路二:在文档外创建一个dom片段,然后把这些数据插入到dom片段中,最后把dom片段插入到列表中。

思路三:用cloneNode创建一个原始列表的副本,把数据插入到副本中,最后用副本来覆盖原始的列表。

思路二的过程,涉及到的dom访问和重排版次数最少,所以只附上思路二的代码:

var fragment = document.createDocumentFragment();//记住这个生成dom片段的方法
appendDataToElement(fragment, data);
document.getElementById('mylist').appendChild(fragment);

    在我们操作元素模拟动画时,也要注意在元素动前把它进行绝对定位,让它脱离文档流,然后移动完成后再恢复。由于脱离文档流,它们在移动的过程中不会引起重排版。

    最后,是一点关于“查询并刷新渲染树改变”的内容,这一部分的文字我读着有点费劲。我认为原版的描述更好理解:Because of the computation costs associated with each reflow, most browsers optimize the reflow process by
queuing changes and performing them in batches. However, you may (often involuntarily) force the queue to be 
flushed and require that all scheduled changes be applied right away. Flushing the queue happens when you want to retrieve layout information, which means using any of the following:

• offsetTop, offsetLeft, offsetWidth, offsetHeight
• scrollTop, scrollLeft, scrollWidth, scrollHeight
• clientTop, clientLeft, clientWidth, clientHeight
• getComputedStyle() (currentStyle in IE)(在 IE 中此函数称为 currentStyle)

所以,不要这么做:

var computed,

tmp = '',
bodystyle = document.body.style;
if (document.body.currentStyle) { // IE, Opera
computed = document.body.currentStyle;
} else { // W3C
computed = document.defaultView.getComputedStyle(document.body, '');
}
bodystyle.color = 'red';
tmp = computed.backgroundColor;
bodystyle.color = 'white';
tmp = computed.backgroundImage;
bodystyle.color = 'green';
tmp = computed.backgroundAttachment;

这样好一些

bodystyle.color = 'red';
bodystyle.color = 'white';
bodystyle.color = 'green';
tmp = computed.backgroundColor;
tmp = computed.backgroundImage;
tmp = computed.backgroundAttachment;

dom优化的部分就到此为止了。

1 0