爱客仕-前端团队博客园

性能之浏览器的重绘与重排

入行几年,想起头几年。插件横飞,flash乱入。

js就像一个寄生的物种,依附浏览器生存,随之而来的是谜之兼容。

入行者得感谢网景,从业者得感谢谷歌

前言

原先打算写一写关于以上的一些个人看法,又中途放弃,因为借助现在琳瑯满目的工具。以上存在的问题都不是问题。最后想了想前端本质还是为页面渲染响应服务,再多工具,只是为了服务自身,控制成本和质量,所以拎出性能这快,来说说自己想法。

浏览器的重绘与重排

简单的先来

那就先讲重绘与重排这快

说这个有先决条件,懂盒子模型的基本概念、知道文档流的概念。

我这里简单说下:

  • 盒子模型简单来说就是关于包含属性宽高和内外边距地一个dom
  • 文档流简单来说就是除了position中的absolute和fixed的dom

———-以上概念可以去谷歌,国内翻译色彩过重,所以还是去阅读英文文档——–

重排(reflow)

重排又称回流(reflow)

一个非常简单的页面载入过程,简单说明:

    1. 用户输入网址,根据协议返回一个html内容(假设没有缓存)  
    1. 载入html代码,发现有css,请求到css内容
    1. 根据css渲染页面   
    1. 继续载入静态资源(img)

当页面css渲染成功以后,一个简单页面就完成了。

不脱离文档流的元素的排列一般会受到子元素,兄弟元素的影响。然后根据盒子模型依次排列好盒子,这就是页面布局的基本绘制。

故,如果其中页面中的任何一个盒子属性发生变化了,那页面就会重排,也就是再一次经历上面说的第三点。

根据css渲染页面   

这就是重排(reflow)

图1

对于重排尴尬的是,程序员本身想控制这个都不可能,类似蝴蝶效应,没法控制一个px最后会影响到什么程度

最后,因为img载入是异步,所以往往在页面全部完成以后,img才姗姗来迟。

所以如果没有控制img的宽高或者在img包裹的那个盒子里,没做高宽,溢出控制。那每完成一个图片载入,就会重新渲染页面

以上就是页面重排

为了减少页面重排影响的浏览器性能问题,我们可以做:

  1. 有图片要页面处理的时候,设置宽高,至少应该控制宽。包裹图片等盒子尽量完整盒子属性

  2. 如果要做动画动效页面,一定要脱离文档流

  3. 活用CSS3 AnimationTransition

  4. 本人现在手机端,在手机端如果频繁reflow,那会出现非常严重的卡顿。CSS3 AnimationTransition 对渲染帮助很大,具体原理脱离了主题不做深究。活用css3在手机端,对于性能提升帮助很大

重绘(repaint)

重绘就是除了基础盒子模型以外一些属性的改变。比如,背景,字体色,文本流

因为是单节点的变化,所以重绘比重排性能损耗来的低很多

重绘来说,没什么好讲,就是减少对dom的操作,直接贴代码,大多数人也应该知道。


代码中过多操作dom [bad](基于jquery)

1
2
3
4
var arr = ["baidu","sina","telcent","ali"];
$.each(arr, function(index, val) {
$('ul')[0].html("<li>" + val + "</li>");
});

代码中合并了dom操作 [good](基于jquery)

1
2
3
4
5
6
7
var arr = ["baidu","sina","telcent","ali"];
var fragment = document.createDocumentFragment();
$.each(arr,function(i,item){
var newItem = $("<li>"+item+"</li>")[0];
fragment.appendChild(newItem);
});
$("ul")[0].appendChild(fragment);