黑马程序员技术交流社区

标题: 【上海校区】深入理解浏览器渲染原理:Repaint, Reflow [打印本页]

作者: frainbowv    时间: 2019-8-16 11:31
标题: 【上海校区】深入理解浏览器渲染原理:Repaint, Reflow
浏览器在下载好HTML、CSS、JS等文件后,是如何将这些内容组装成绚丽的页面呈现给用户呢?这儿我们可以深入了解一下这个过程:
渲染过程不同的浏览器渲染过程实际上并不相同,但是依旧存在相一致的部分,大致过程如下图:
森林和树我们先看一段HTML代码:
[JavaScript] 纯文本查看 复制代码
<html>
<head>
  <title>Beautiful page</title>
</head>
<body>
   
  <p>
    Once upon a time there was
    a looong paragraph...
  </p>
  
  <div style="display: none">
    Secret message
  </div>
  
  <div>![](...)</div>
  ...

</body>
</html>
其DOM树大致如此:
[HTML] 纯文本查看 复制代码
documentElement (html)
    head
        title
    body
        p
            [text node]
        
        div
            [text node]
        
        div
            img
        
        ...
渲染树为DOM树中可视的部分:
[HTML] 纯文本查看 复制代码
root (RenderView)
    body
        p
            line 1
            line 2
            line 3
            ...
        
        div
            img
        
    ...
渲染树的根结点囊括了所有的可视元素,它是浏览器窗口的一部分,并且能够进行伸缩调整。一般来说,渲染区域为自浏览器左上角(0,0)起始,终止于右下角(window.innerWidth, window.innerHeight)的矩形部分。重绘与回流当第一次打开一个页面时,至少会有一次重绘和回流。之后,如果渲染树发生了变动,那么可能会触发重绘或回流中的一个或二者。
重绘与回流都会导致体验上的不佳。
触发Repaint或Reflow我们具体看看哪些操作会导致重绘或回流:
我们看些例子:
[JavaScript] 纯文本查看 复制代码
var bstyle = document.body.style; // cache

bstyle.padding = "20px"; // reflow, repaint
bstyle.border = "10px solid red"; // another reflow and a repaint

bstyle.color = "blue"; // repaint only, no dimensions changed
bstyle.backgroundColor = "#fad"; // repaint

bstyle.fontSize = "2em"; // reflow, repaint

// new DOM element - reflow, repaint
document.body.appendChild(document.createTextNode('dude!'));
有些reflow的操作代价会比一般的高出许多。可以试着想象出一棵渲染树,如果只是自上而下的对某些dom进行一些宽高等方面的调整,那么并不会导致整棵渲染树太大的变动,而如果是频繁调整部分结点在整个渲染树的位置,这种调整往往是“牵一而动全身”,代价就会非常高了。
浏览器的处理方式既然渲染树的reflow或repaint的代价十分高昂,那么不得不采取一些优化的方式,浏览器对此有一些针对性的举措。一种策略便是延迟。浏览器会将一些变动放在一个队列中,当达到一定规模或者延迟的时间已到,那么会一次将这些变动反应到渲染树中。但是这种策略会有一定的弊端,当我们执行一些脚本时可能会导致浏览器不得不提前让repaint或reflow进行完毕,例如我们需要获取一些样式信息时,诸如:
[JavaScript] 纯文本查看 复制代码
offsetTop, offsetLeft, offsetWidth, offsetHeight
scrollTop/Left/Width/Height
clientTop/Left/Width/Height
getComputedStyle(), or currentStyle in IE

  为了让JS获取到最终的样式,浏览器不得不将缓冲队列里reflow或repaint过程执行完毕。所以,我们一般需要避免一连串的设置或获取dom样式:
[JavaScript] 纯文本查看 复制代码
// no-no!el.style.left = el.offsetLeft + 10 + "px";

压缩repaints或reflows我们有一些策略去尽量消除或减小reflow/repaint所带来的负面影响。
[JavaScript] 纯文本查看 复制代码
// badvar left = 10,    top = 10;el.style.left = left + "px";el.style.top  = top  + "px"; 
// better el.className += " theclassname";
// or when top and left are calculated dynamically...
// betterel.style.cssText += "; left: " + left + "px; top: " + top + "px;";
[JavaScript] 纯文本查看 复制代码
// no-no!for(big; loop; here) {    el.style.left = el.offsetLeft + 10 + "px";    el.style.top  = el.offsetTop  + 10 + "px";} 
// bettervar left = el.offsetLeft,    top  = el.offsetTop    esty = el.style;for(big; loop; here) {    left += 10;    top  += 10;    esty.left = left + "px";    esty.top  = top  + "px";}





文章转载至:https://www.jianshu.com/p/40c6fc1d4800



作者: Port    时间: 2019-8-16 17:01





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2