您现在的位置:首页 >> 前端 >> 内容

从基础做起--浏览器渲染

时间:2017/8/5 14:51:09 点击:

  核心提示:从基础做起--浏览器渲染,先从浏览器构成开始。浏览器的主要构成(High Level Structure)浏览器的主要组件包括:1.用户界面 - 包括地址栏、后退/前进按钮、书签目录等,也就是你所看到...

从基础做起--浏览器渲染,先从浏览器构成开始。

浏览器的主要构成(High Level Structure)

浏览器的主要组件包括:

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

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

3.渲染引擎 - 用来显示请求的内容,例如,如果请求内容为html,它负责解析html
及css,并将解析后的结果显示出来。

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

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

6. JS解释器 - 用来解释执行JS代码。

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

如图 1.1 所示

从基础做起--浏览器渲染

图 1.1

在众多浏览器中,Chrome 浏览器为每个Tab分配了各自的渲染引擎实例,每个Tab就是一个独立的进程。什么是渲染引擎?

渲染引擎(The rendering engine)


主流程(The main flow)

在取得通过网络请求的文档以后,渲染引擎的基本流程:

解析html构建dom树

构建render树

布局render树

绘制render 树

如图 1.2 所示

从基础做起--浏览器渲染

图1.2

渲染伊始,解析html标签,生成DOM结构,然后解析CSS层叠样式表,根据结果构建Render树。Render树由一些包含有颜色和大小等属性的矩

形组成,按顺序排列,然后开始布局,确定结点的坐标,最后绘制,遍历Render树,使用UI后端绘制。

注意这个过程是边解析边显示的,并非解析完所有结构才显示网页内容。

渲染树和Dom树的关系(The render tree relation to the DOM tree)

渲染对象和元素相对应,但这种对应关系不是一对一的,不可见的DOM元素不会被插入渲染树,例如head元素。另

外,display属性为none的元素也不会在渲染树中出现(visibility属性为hidden的元素将出现在渲染树中)。

还有一些DOM元素对应几个可见对象,它们一般是一些具有复杂结构的元素,无法用一个矩形来描述。例如,select元素有三

个渲染对象——一个显示区域、一个下拉列表及一个按钮。同样,当文本因为宽度不够而折行时,新行将作为额外的渲染元素被添

加。另一个多个渲染对象的例子是不规范的html,根据CSS规范,一个行内元素只能仅包含行内元素或仅包含块状元素,在存在混

合内容时,将会创建匿名的块状渲染对象包裹住行内元素。一些渲染对象和所对应的DOM节点不在树上相同的位置,例如,浮动和

绝对定位的元素在文本流之外,在两棵树上的位置不同,渲染树上标识出真实的结构,并用一个占位结构标识出它们原来的位置。

如图 1.3 所示

从基础做起--浏览器渲染

图 1.3

创建树的流程(The flow of constructing the tree)

处理html和body标签将构建渲染树的根,这个根渲染对象对应被CSS规范称为containing block的元素——包含了其他所有

块元素的顶级块元素。它的大小就是viewport——浏览器窗口的显示区域,文档指向的渲染对象。

样式计算(Style Computation)

样式数据是非常大的结构,保存大量的样式属性会带来内存问题。不进行优化,找到每个元素匹配的规则会导致性能问题。

 

Specifity

CSS2规范中定义的选择符specifity如下:

如果声明来自style属性,而不是一个选择器的规则,则计1,否则计0(=a)

计算选择器中id属性的数量(=b)

计算选择器中class及伪类的数量(=c)

计算选择器中元素名及伪元素的数量(=d)

连接a-b-c-d四个数量(用一个大基数的计算系统)将得到specifity,根据改值确定优先级。

布局

当渲染对象被创建并添加到树中,它们并没有位置和大小,计算这些值的过程称为layout(webkit)或reflow(Gecko)。

Html使用基于流的布局模型,意味着大部分时间,可以以单一的途径进行几何计算。流中靠后的元素并不会影响前面元素的几何特

性,所以布局可以在文档中从右向左、自上而下的进行。也存在一些例外,比如html tables。

坐标系统相对于根frame,使用top和left坐标。布局是一个递归的过程,由根渲染对象开始,它对应html文档元素,布局

继续递归的通过一些或所有的通过一些或所有的frame层级,为每个需要几何信息的渲染对象进行计算。所有的渲染对象都有一

个layout或reflow方法,每个渲染对象调用需要布局的children的layout方法。

Dirty bit系统

为了不因为每个小变化都全部重新布局,浏览器使用一个dirty bit系统,一个渲染对象发生了变化或是被添加了,就标记它及

它的children为dirty——需要layout。存在两个标识——个标识——dirty及children are dirty,children are dirty说明即使

这个渲染对象可能没问题,但它至少有一个没问题,但它至少有一个child需要layout。

全局和增量layout

当layout在整棵渲染树触发时,称为全局layout,这可能在下面这些情况下发生:

1.一个全局的样式改变影响所有的渲染对象,比如字号的改变。

2.窗口resize。

layout也可以是增量的,这样只有标志为dirty的渲染对象会重新布局(也将导致一些额外的布局)。增量layout会在渲染

对象dirty时异步触发,例如,当网络接收到新的内容并添加到容并添加到DOM树后,新的渲染对象会添加到渲染树中。

layout过程

layout一般有下面这几个部分:

1. parent渲染对象决定它的宽度

2. parent渲染对象读取chilidren,并:

a.放置child渲染对象(设置它的x和y)。

b.在需要时(它们当前为dirty或是处于全局layout或者其他原因)调用child渲染对象的layout,这将计算child的高度

c. parent 渲染对象使用 child 渲染对象的累积高度,以及margin和padding的高度来设置自己的高度-这将被parent渲染

对象的 parent 使用。

d.将dirty标识设置为false。

Line breaking

当一个渲染对象在布局过程中折行时,则暂停告诉它的 parent 需要折行,parent将创建额外的渲染对象并调用它的layout。


绘制(Painting)

绘制阶段,遍历渲染树并调用渲染对象的 paint 方法将它们的内容显示在屏幕上,绘制使用UI基础组件。

全局和增量

和布局一样,绘制也可以是全局的——绘制完整的树——或增量的。在增量的绘制过程中,一些渲染对象以不影响整棵树的方

式改变,改变的渲染对象使其在屏幕上的矩形区域失效,这将导致操作系统将其看作dirty区域,并产生一个paint事件,操作系

统很巧妙的处理这个过程,并将多个区域合并为一个。Chrome中,这个过程更复杂些,因为渲染对象在不同的进程中,而不是在

主进程中。Chrome在一定程度上模拟操作系统的行为,表现为监听事件并派发消息给渲染根,在树中查找到相关的渲染对象,重

绘这个对象(往往还包括它的children)。

绘制顺序

这个是元素压入堆栈的顺序,这个顺序影响着绘制,堆栈从后向前进行绘制。

一个块渲染对象的堆栈顺序是:

1. 背景色

2. 背景图

3. border

4. children

5. outline

渲染引擎的线程

渲染引擎是单线程的,除了网络操作以外,几乎所有的事情都在单一的线程中处理,在Firefox和Safari中,这是浏览器的主

线程,Chrome中这是tab的主线程。网络操作由几个并行线程执行,并行连接的个数是受限的(通常是2-6个)。

 

定位策略Position scheme

这里有三种策略:

1. normal-对象根据它在文档中位置定位,这意味它在渲染树和在DOM树中位置一致,根据它的盒模型和大小进行布局。

2. float-对象先像普通流一样布局,然后尽可能的向左或是向右移动。

3. absolute-对象在渲染树中的位置和DOM树中位置无关。

static和relative是normal,absolute和fixed属于absolute。在static定位中,不定义位置而使用默认的位置。其他策

略中,作者指定位置——top、bottom、left、right。

Layered representation

这个由CSS属性中的z-index指定,表示盒模型的第三个大小,即在z轴上的位置。Box分发到堆栈中(称为堆栈上文),

每个堆栈中靠后的元素将被较早绘制,栈顶靠前的元素离用户最近,当发生交叠时,将隐藏靠后的元素。堆栈根据z-index属性排

序,拥有z-index属性的box形成了一个局部堆栈,viewport有外部堆栈。

作者:网络 来源:YiCheng_L的