zoukankan      html  css  js  c++  java
  • 页面的重绘与回流

       上次在面试中,面试官问了我一个关于页面重绘和回流的问题,我解释的不怎么好。今天把它整理了一下,又参考了一些其他的文章。

      参考文章:http://www.css88.com/archives/4996

      页面加载过程

         1、浏览器将获取到的HTML代码解析成一个DOM树,HTML中的每一个标签都是DOM树中的一个节点,根节点就是document。DOM树中包含了所有的HTML标签,同时也包含了display:none 隐藏和JS动态添加的元素等

         2、浏览器将所有的样式(CSS)解析成样式结构体(CSS Model),在解析过程中会去掉浏览器不识别的样式。

         3、DOM Tree 和样式结构体组合后构建render tree。 render tree类似于DOM tree。但是有较大差别。render树中的每个节点都有自己的样式,但是render tree中不包含display:none的元素。但是visiblity:hidden的隐藏元素会包含在render Tree中。因为visibility:hidden会影响布局(layout),且在文档流中占据一定的空间。

           4、一旦render Tree 构建完毕,浏览器就可以根据render tree绘制页面了

      回流与重绘

      1、什么是回流?

        当render tree 中的一部分(或者全部)因为元素的规模尺寸、布局隐藏等改变需要重新构建。这就是回流。

      2、什么是重绘?

        在回流的时候,浏览器会使渲染树中受影响的部分失效,并重新绘制这部分的渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘

      3、什么情况下浏览器会发生重绘?

        重绘不一定引起回流,但是回流一定会影响重绘。只是改变某些元素的属性并且这些属性会影响到元素的外观、风格,不会影响页面的布局,比如backgorund-color;color等;visability:hidden只重绘不回流

      4、什么情况下,浏览器会发生回流?(重要)

        当页面布局或者几何大小发生变化时就会发生回流。

        ①添加或删除可见的DOM元素;

        ②元素的位置变化

        ③元素的尺寸变化--内容区域、边框、内外边距、宽高

        ④内容改变--文本内容改变或者图片大小改变而引起的计算值宽度和高度改变

        ⑤页面渲染的初始化

        ⑥浏览器可视窗口变化---resize时间发生时、或者浏览器的字体大小改变时(用户操作)

             聪明的浏览器 (见文章 http://www.css88.com/archives/4996;写的很好)

        如何优化页面?

        减少回流和重绘就是减少对render tree的操作(合并多次DOM修改和样式修改),减少对一些元素style的请求。具体方法如下:

        1、同时添加子元素和父元素时,应先在内存中将子元素拼接到父元素中,最后在整体一次性将父元素添加到文档流中---这样只会发生一次layout

        2、如果多次同时添加多个平级元素时,应该使用文档片段

        什么是文档片段:内存中临时存储的多个平级子元素的虚拟父元素

          何时使用: 只要是添加多个平级的子元素时,都要先将子元素加入到文档片段中,再一次性将文档片段添加到DOM树

                实例如下:          

    使用文档片段
    <ul id="container"> </ul> <script type="text/javascript"> var container = document.getElementById('container'); console.time(); var fragment = document.createDocumentFragment(); for(var i = 0;i<50000;i++){ fragment.appendChild(document.createElement('li')); } container.appendChild(fragment); console.timeEnd(); </script>
    //总耗时default: 76.31201171875ms
    不使用文档片段

    <script type="text/javascript">
        var container = document.getElementById('container');
    console.time();
    for(var i = 0;i<50000;i++){
    container.appendChild( document.createElement('li'))
    }
    console.timeEnd();
    </script>
    //default: 88.941162109375ms

      3、直接改变className,如果动态改变样式,可以使用cssText

      4、由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂的操作时,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发2次重排。 

      5、使用cloneNode(true/false)和replaceChild 技术,引发一次回流和重绘

      6、不要经常访问会引起浏览器flush队列的属性,如果确实要访问的话,可以利用缓存;也就是说需要经常去那些引起浏览器重排的属性时,需要缓存到变量中,再调用。

      7、让元素脱离动画流,减少回流的Render Tree的规模

                     

      

  • 相关阅读:
    jquery 中的 map each has
    jquery的 dom操作
    jquery的 包装集
    JQuery 的了解之 选择器
    JS 中闭包的变量 闭包与this
    IPhone下json的解析 NSJSONSerialization
    IIS上部署MVC网站,打开后ExtensionlessUrlHandler-Integrated-4.0解决办法
    win7系统的用户去掉用户账户控制 提升管理员
    移动开发在路上-- IOS移动开发系列 多线程三
    MVC 入门 自动生成 增删改查所有功能
  • 原文地址:https://www.cnblogs.com/bllx/p/8611122.html
Copyright © 2011-2022 走看看