这张主要分5个环节寻行渐近的回答,分别是【什么是DOCTYPE及作用】、【浏览器渲染过程】、【重绘Reflow】、【重绘Repaint】,很多都是直接通过本人用大白话讲。
一、什么是DOCTYPE及作用
1.DTD(文档类型定义):DTD就是告诉浏览器我是什么类型,浏览器根据这个判断用什么来解析渲染它。而DOCTYPE就是告诉浏览器是哪个DTD(文档类型)
比如:
① h5方式的,<!DOCTYPE html>,其中html就是DTD的其中一种类型
②HTML4.01 Strict(记住这个就行,下面太长记不住)
<!DOCTYPE HTMLPUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
③传统模式 Transitional(记住这个就行,下面太长记不住)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
二、浏览器渲染过程
我们来看一张图
我们介绍流程:
①首先HTML通过HTML解析器变成DOM Tree。
②样式表通过css解析器变成CSS Rules Tree。
③DOM Tree 与CSS Tree 合并成为Render Tree
④ Layout布局Render Tree
⑤Painting绘制Render Tree
一些重要的概念:
DOM Tree:浏览器将HTML解析成树形的数据结构。
CSS Rule Tree:浏览器将CSS解析在树形的数据结构.
Render Tree:DOM和CSSOM(CSS Object Model:CSS对象模型)合并后生成Render Tree.
layout:有了Render Tree,浏览器已经能知道网页中有哪些节点,各个节点的CSS的定义以及他们的从属关系,从而去计算出每个节点的屏幕中的位置.
painting:按照算出来的规则,通过显卡,把内容画到屏幕上.
reflow(重绘):当浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,称此为回退的过程,叫reflow.reflow会从<html>这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置。feflow几乎是无法避免的.
三、重排Reflow
repaint(重排):也叫回流,DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器通过各种样式计算结果将元素放到它该出现的位置,这个过程叫做重排。
怎么会触发重排:
- dom元素的位置和尺寸大小的变化
- dom元素的增加和删除
- 伪类的激活
- 窗口大小的变化
- 增加和删除class样式
- 动态计算修改css样式
当然,我们的浏览器不会每一次reflow都立刻执行,而是会积攒一批,这个过程也被成为异步reflow,或者增量异步reflow。但是有些情况浏览器是不会这么做的,比如:resize窗口,改变了页面默认的字体,等。对于这些操作,浏览器会马上进行reflow。
四、重绘Repaint
Repaint(重绘):指css样式的改变,但元素的大小和尺寸不变,而导致节点的重新绘制。
怎么样子又会触发重绘:
任何对元素样式,如background-color
、border-color
、visibility
等属性的改变。css 和 js 都可能引起重绘。
如何尽量减小重绘:
就是先生成DOM片段,然后一次性加入到这个节点。
代码示例:
$('body').css('color', 'red'); // repaint
$('body').css('margin', '2px'); // reflow, repaint
var bstyle = document.body.style; // cache
bstyle.padding = "20px"; // reflow, repaint
bstyle.border = "10px solid red"; // 再一次的 reflow 和 repaint
bstyle.color = "blue"; // repaint
bstyle.backgroundColor = "#fad"; // repaint
bstyle.fontSize = "2em"; // reflow, repaint
// new DOM element - reflow, repaint
document.body.appendChild(document.createTextNode('dude!'));
注意点:
1.display:none的节点不会被加入Render Tree,而visibility:hidden则会,所以如果某个节点最开始是不显示的,设为display:none是最好的
参考文章:
https://segmentfault.com/a/1190000016458627#item-4