• 浏览器原理、重绘、回流、性能优化-学习总结


    1 浏览器的组成

    image-20201231142258251

    • 用户界面- 包括地址栏后退/前进按钮、书签目录等,也就是除了用来显示所请求页面的主窗口之外的其他部分

    • 浏览器引擎- 用来查询及操作渲染引擎的接口

    • 渲染引擎(浏览器内核)- 用来显示请求的内容,例如,如果请求内容为html,它负责解析html及css,并将解析后的结果显示出来

    • 网络- 用来完成网络调用,例如http请求,它具有平台无关的接口,可以在不同平台上工作

    • UI 后端- 用来绘制类似组合选择框及对话框等基本组件,具有不特定于某个平台的通用接口,底层使用操作系统的用户接口

    • JS解释器- 用来解释执行JS代码

    • 数据存储- 属于持久层,浏览器需要在硬盘中保存类似cookie的各种数据,HTML5定义了Storage技术,这是一种轻量级完整的客户端存储技术

    2 主流的渲染引擎

    浏览器的渲染引擎也叫排版引擎,或者是浏览器内核

    主流的 渲染引擎 有

    • Chrome浏览器: Blink引擎(WebKit的一个分支)。
    • Safari浏览器: WebKit引擎,windows版本2008年3月18日推出正式版,但苹果已于2012年7月25日停止开发Windows版的Safari。
    • FireFox浏览器: Gecko引擎。
    • Opera浏览器: Blink引擎(早期版使用Presto引擎)。
    • Internet Explorer浏览器: Trident引擎 。
    • Microsoft Edge浏览器: EdgeHTML引擎(Trident的一个分支)。

    3 渲染引擎工作原理

    渲染引擎解析的基本流程:

    1. 解析HTML构建Dom树,DOM 是W3C组织推荐的处理可扩展置标语言的标准编程接口。
    2. 构建渲染树,渲染树并不等同于Dom树,因为像`head`标签 或 `display: none`这样的元素就没在渲染树中了,但是它们在Dom树中。
    3. 对渲染树进行布局,定位坐标和大小、确定是否换行、确定position、overflow、z-index等等,这个过程叫`layout` 或 `reflow`。
    4. 绘制渲染树,调用操作系统底层API(UI Backend)进行绘图操作。
    

    image-20201231144053873

    webkit内核工作流程

    img

    gecko内核工作流程

    image-20201231145936654

    4 性能优化:重绘与回流(重排)

    回流(reflow)与重绘(repaint),在性能优化的时候十分重要,面试也经常被提及。

    回流(reflow):当渲染树(render tree)中一部分(或全部)元素的规模尺寸,布局,隐藏等改变而需要重新构建。

    重绘(repaint):当渲染树(render tree)中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。

    小结: 影响布局的操作会发生回流;不影响布局而只是修改颜色等属性则发生重绘;

    ​ 每个页面至少需要一次回流+重绘

    ​ 回流必将引起重绘

    回流(重排)发生的条件

    1、添加或者删除可见的DOM元素;

    2、元素位置改变;

    3、元素尺寸改变——边距、填充、边框、宽度和高度

    4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;

    5、页面渲染初始化;

    6、浏览器窗口尺寸改变——resize事件发生时;

    【重排和重绘案例.html】

    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!'));
    

    优化方案

    原理:尽量减少重绘与回流的次数

    方案1

    直接使用className修改样式,少用style设置样式.

    div.classList.add('test');   //一次重排 重绘 
    

    方案2

    把要频繁操作的元素从渲染树中去除;比如使用display:none;

    div.style.display = 'none';//第一次 重排 重绘
    div.style.width = 200px;
    div.style.heigt= 200px; 
    div.style.color = 'red';
    div.style.margin = 20px;
    div.style.display = 'block';//第二次 重排 重绘
    
    这里总共发生两次重绘和重排 
    

    方案3

    布局经常改变的盒子进行定位脱标, 比如动画 先定位 ,建议使用css3动画和变换 transform

    方案4

    使用DocumentFragment(虚拟dom)进行缓存操作,引发一次回流和重绘

    	var pNode,fragment = document.createDocumentFragment(); 
        //动态创建20个p标签,先用DocumentFragment 对象来缓存     
        for(var i=0; i<20; i++){
            pNode = document.createElement('p');
            pNode.innerHTML = i;
            fragment.appendChild(pNode);
        }
        document.body.appendChild(fragment);
    

    优化总结

    • 加类名:把多个css属性放到一个类中,减少回流和重绘的次数
    • 将样式修改代码加到两个display:none中间
    • 让布局经常改变的盒子脱离标准流
    • 使用虚拟dom DocumentFragment
  • 相关阅读:
    【Ubuntu 笔记】翻译 32.1 Job Control
    【Class 学习笔记】 浮点数的储存,运算
    【Ubuntu学习笔记】 安装篇-锐捷、scim、root改密码
    【Ubuntu学习笔记】安装篇-网络配置遇到的问题
    MySQL增删改查
    Spring MVC详解
    SSH和SSM对比总结
    hibernate工作原理
    JavaBean与xml互转的方法详解
    spring MVC如何获取session传值到前台
  • 原文地址:https://www.cnblogs.com/helf/p/14217092.html
Copyright © 2020-2023  润新知