zoukankan      html  css  js  c++  java
  • 浏览器的渲染页面过程和重排、重绘

    渲染页面的过程:

    1.解析html源码,创建dom树。每个标签都是一个节点。

    2.解析css

    3.构建dom树,并且计算出样式(padding、margin等),然后构建 渲染树。对于渲染树和dom树的不同是:dom树的每一个标签都是一个节点,但是渲染树会忽略掉不需要渲染的元素,例如head、display:none的元素。渲染树中的每一个节点都存储有对应的css属性。

    4.渲染树创建好后,浏览器就可以根据渲染树直接把页面绘制到屏幕上。

    重排和重绘:

    重排:就是渲染树的一部分必须要更新 并且节点的尺寸发生了变化。这就会触发重排操作(相当于渲染树需要重新计算.....)。

    重绘:部分节点需要更新,但是没有改变他的集合形状,比如改变了背景颜色,这就会触发重绘。

    产生重排或重绘的操作:

    (1)增加或删除DOM节点
    (2)设置 display: none;(重排并重绘) 或者 visibility: hidden(只有重排)
    (3)移动页面中的元素

    (4)增删或者修改样式

    (5)计算offsetWidth和offsetHeight

    (6)用户 改变窗口大小,滚动页面等

    浏览器的处理方案:

    因为渲染树的改变导致的重绘或重排操作都可能代价很高,浏览器会对这个改动做很多优化。

    一个策略就是不要立即做操作,而是批量进行。比如把你的脚本对DOM的修改放入一个队列,在队列所有操作结束后只需要进行一次绘制即可。


    但是有的时候脚本可能会导致浏览器的批量优化无法进行,可能在清空队列之前就需要重新绘制(绘制意思是重绘或者重排)页面。比如你通过脚本获取这些样式:

    offsetTop, offsetLeft, offsetWidth, offsetHeight
    scrollTop/Left/Width/Height
    clientTop/Left/Width/Height
    getComputedStyle(), or currentStyle in IE

    因为浏览器必须给你最新的值,所以当你进行这些取值操作的时候会立刻触发一次页面的绘制。这样本来可以批量修改样式然后一次性绘制的方法就无法使用了。

    最后来说以下解决办法:

    1.不要一个一个地单独修改属性,最好通过一个classname来定义这些修改

    2.把对节点的大量修改操作放在页面之外,用 documentFragment来做修改,clone 节点,在clone之后的节点中做修改,然后直接替换掉以前的节点。
    通过 display: none 来隐藏节点(直接导致一次重排和重绘),做大量的修改,然后显示节点(又一次重排和重绘),总共只会有两次重排。

    3.不要频繁获取计算后的样式。如果你需要使用计算后的样式,最好暂存起来而不是直接从DOM上读取。

    4.减少table布局(话说,很少有用table布局的了吧 现在,都过时了....)

    5.避免css表达式,(因为每当文档重新加载或者部分文档重新加载的时候,CSS表达式都会重新计算一次,因此其性能会受到非常大的影响。)

    6.总的来说,总是考虑到渲染树得存在,考虑到你的一次修改会导致多大的绘制操作。(比如绝对定位元素的动画就不会影响其他大部分元素)。

  • 相关阅读:
    ios开发之多线程---GCD
    三:新浪微博--主框架的搭建
    二:新浪微博:第三方框架管理工具CocoaPods的安装和使用
    PHP Fatal Error: call to undefined function mysql_connect() [duplicate]
    ZooKeeper 3.4.5 分布式环境搭建详解
    coreLocation说明,作者写的很用心,收藏
    动画设置参数,有数值,收藏了
    Java 设计模式——组合模式
    NSURL基本操作示例说明
    关于应用程序启动,你可能不知道的东西
  • 原文地址:https://www.cnblogs.com/xinxingyu/p/4783080.html
Copyright © 2011-2022 走看看