回流与重绘

浏览器的渲染机制:

浏览器渲染页面一般分为五个步骤

1、处理HTML并构建DOM树

2、处理css构建CSSOM树

3、将DOM和CSSOM树合并成一个渲染树

4、根据渲染树来布局,计算每个节点的位置

5、调用GPU绘制,合并图层,显示在屏幕上

重绘:当我们对DOM的修改导致了样式的变化,却并未影响其几何属性(比如修改字体颜色、背景颜色等),浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式(跳过了上图所示的回流环节)。这个过程叫做重绘。

回流:当我们对 DOM 的修改引发了 DOM 几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性(其他元素的几何属性和位置也会因此受到影响),然后再将计算的结果绘制出来。这个过程就是回流(也叫重排)。

导致回流的几种情况:

1、页面初始化

2、浏览器窗口缩放

3、改变元素的边距、填充、宽、高、边框

4、offset、scroll、client等属性是由计算获得的,浏览器为了获取这些值也会回流

5、当我们调用了 getComputedStyle 方法,或者 IE 里的 currentStyle 时,也会触发回流。原理是一样的,都为求一个“即时性”和“准确性”。

涉及到的css属性有margin,padding,height,width,border,display,min-height,position,top,right,bottom,left,float,clear,line-height,text-align,overflow,overflow-y,font-weight,font-family,font-size,white-space等

导致重绘的情况

css 属性中,color 、border-style、border-radius、visibility、text-decoration、box-shadow、background、background-image、background-position、background-repeat、background-size、outline、outline-color等属性变更。

动动手

var s = document.body.style;
s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 再一次 回流+重绘
s.color = "blue"; // 再一次重绘
s.backgroundColor = "#ccc"; // 再一次 重绘
s.fontSize = "14px"; // 再一次 回流+重绘
// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));
//requestAnimationFrame是什么呢?
//他也是个计时器

//与setTimeout和setInterval不同,
//requestAnimationFrame不需要设置时间间隔

//setTimeout和setInterval的问题是,它们都不精确。
//它们的内在运行机制决定了时间间隔参数实际上只是
//指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。
//如果队列前面已经加入了其他任务,
//那动画代码就要等前面的任务完成后再执行

//requestAnimationFrame采用系统时间间隔,
//保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;
//也不会因为间隔时间太长,使用动画卡顿不流畅,
//让各种网页动画效果能够有一个统一的刷新机制,
//从而节省系统资源,提高系统性能,改善视觉效果

      //【1】requestAnimationFrame会把每一帧中的所有DOM操作集中起来,
        //  在一次重绘或回流中就完成,
        //  并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率

  //【2】在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,
         // 这当然就意味着更少的CPU、GPU和内存使用量

  //【3】requestAnimationFrame是由浏览器专门为动画提供的API,
        // 在运行时浏览器会自动优化方法的调用,
         // 并且如果页面不是激活状态下的话,动画会自动暂停,
          //有效节省了CPU开销





//控制台输出1和0
var timer = requestAnimationFrame(function(){
    console.log(0);
}); 
console.log(timer);//1
        


//控制台什么都不输出
var timer = requestAnimationFrame(function(){
    console.log(0);
}); 
cancelAnimationFrame(timer);

//cancelAnimationFrame方法用于取消定时器

参考:

文献1:https://www.cnblogs.com/yangyangxxb/p/10081546.html

文献2:https://www.chaojimake.cn/questioninfo_188.html

posted @ 2024-01-18 11:34  徐学进  阅读(44)  评论(0)    收藏  举报