摘要:渲染引擎的概述渲染引擎的主要职责是在浏览器屏幕上显示请求的页面。中,渲染树中的每个节点都被称为的渲染器或渲染对象。坐标系相对于根渲染器。增量只有一些渲染器以不影响整个树的方式进行更改。渲染器使其矩形在屏幕上无效。
到目前为止,在我们之前的“JavaScript工作原理”系列文章中,我们一直关注JavaScript作为一种语言,其功能,它如何在浏览器中执行,如何优化等等。
但是,当您构建Web应用程序时,您不只是编写独立运行的独立JavaScript代码。您编写的JavaScript与环境进行交互。了解这种环境,它是如何工作的以及它的组成是什么,将使您能够构建更好的应用程序,并对应用程序发布后可能出现的潜在问题做好充分准备。
那么,让我们看看浏览器的主要组件是什么:
用户界面:这包括地址栏,后退和前进按钮,书签菜单等。实质上,这是浏览器显示的每个部分,除了您看到网页本身的窗口。
浏览器引擎:它处理用户界面和渲染引擎之间的交互
渲染引擎:它负责显示网页。渲染引擎解析HTML和CSS,并在屏幕上显示解析的内容。
网络:这些是网络调用,例如XHR请求,通过对不同平台使用不同的实现来实现,这些平台位于独立于平台的接口之后。在本系列的前一篇文章中,我们更详细地讨论了网络层。
UI后端:用于绘制核心小部件,如复选框和窗口。这个后端公开了一个不是平台特定的通用接口。它使用下面的操作系统UI方法。
JavaScript引擎:我们在该系列的前一篇文章中详细介绍了这一点。基本上,这是JavaScript执行的地方。
数据持久性:您的应用可能需要在本地存储所有数据。支持的存储机制类型包括localStorage,indexDB,WebSQL和FileSystem。
在这篇文章中,我们将关注渲染引擎,因为它处理HTML和CSS的解析和可视化,这是大多数JavaScript应用程序不断与之交互的东西。
渲染引擎的概述渲染引擎的主要职责是在浏览器屏幕上显示请求的页面。
渲染引擎可以显示HTML和XML文档和图像。如果您使用额外的插件,引擎还可以显示不同类型的文档,如PDF。
渲染引擎与JavaScript引擎类似,不同的浏览器也使用不同的渲染引擎。这些是一些流行的:
Gecko - 火狐
WebKit - Safari
Blink - Chrome,Opera(从15版开始)
渲染的过程渲染引擎从网络层接收所请求文档的内容。
构建DOM树
渲染引擎的第一步是解析HTML文档并将解析的元素转换为DOM树中的实际DOM节点。
想象一下你有以下的文字输入:
Hello, friend!
这个HTML的DOM树如下所示:
基本上,每个元素都被表示为所有其子元素的父节点子元素直接包含在它的内部。
CSSOM指的是CSS对象模型。当浏览器构建页面的DOM时,它在引用外部theme.css CSS样式表的head部分遇到link标记。预计它可能需要该资源来呈现页面,它立即发出请求。假设theme.css文件包含以下内容:
body { font-size: 16px; } p { font-weight: bold; } span { color: red; } p span { display: none; } img { float: right; }
与HTML一样,引擎需要将CSS转换为浏览器可以使用的东西 - CSSOM。 以下是CSSOM树的外观:
你想知道为什么CSSOM有一个树结构?当计算页面上任何对象的最后一组样式时,浏览器从适用于该节点的最一般规则开始(例如,如果它是body元素的子元素,则应用所有body样式),然后递归地细化通过应用更具体的规则来计算样式。
让我们来看看我们给出的具体例子。包含在body元素中的span标签中的任何文本的字体大小为16像素,并且具有红色。这些样式是从body元素继承而来的。如果span元素是p元素的子元素,则由于正在应用更具体的样式,因此不会显示其内容。
另外请注意,上面的树不是完整的CSSOM树,只显示了我们决定在样式表中重写的样式。每个浏览器都提供了一组默认的样式,也称为“user agent styles” - 这是我们在没有明确提供任何样式时看到的。我们的样式简单地覆盖这些默认值。
构建渲染树HTML中的可视指令与CSSOM树中的样式数据结合在一起用于创建渲染树。
你可能会问什么是渲染树?这是按照它们在屏幕上显示的顺序构建的视觉元素树。它是HTML和相应的CSS的可视化表示。此树的目的是为了以正确的顺序绘制内容。
Webkit中,渲染树中的每个节点都被称为的渲染器或渲染对象。
这就是上述DOM和CSSOM树的渲染器树的外观:
为了构建渲染树,浏览器大致如下:
从DOM树的根开始,它遍历每个可见节点。某些节点不可见(例如,脚本标记,元标记等),并且由于它们未反映在呈现的输出中而被忽略。一些节点通过CSS隐藏,并且也从渲染树中省略。例如,span节点 - 在上面的例子中,它并不存在于渲染树中,因为我们有一个明确的规则来设置display:none属性。
对于每个可见节点,浏览器找到适当的CSSOM规则并应用它们。
它发出带有内容及其计算样式的可见节点
你可以在这里看看RenderObject的源代码(在WebKit中):https://github.com/WebKit/web...
我们来看看这个类的一些核心内容:
class RenderObject : public CachedImageClient { // Repaint the entire object. Called when, e.g., the color of a border changes, or when a border // style changes. Node* node() const { ... } RenderStyle* style; // the computed style const RenderStyle& style() const; ... }
每个渲染器代表一个矩形区域,通常对应于一个节点的CSS框。它包括几何信息,例如宽度,高度和位置。
渲染树的布局当渲染器被创建并添加到树中时,它没有位置和大小。计算这些值称为布局。
HTML使用基于流程的布局模型,这意味着大部分时间内它可以通过一次传递计算几何。坐标系相对于根渲染器。使用顶部和左侧坐标。
布局是一个递归过程 - 它从根呈现器开始,它对应于HTML文档的元素。布局通过部分或整个渲染器层次结构递归地继续递归,为需要它的每个渲染器计算几何信息。
根渲染器的位置是0,0,并且其尺寸具有浏览器窗口(也称为视口)的可见部分的尺寸。
开始布局过程意味着给每个节点确切的坐标,它应该出现在屏幕上。
绘制渲染树在此阶段中,遍历渲染器树并调用渲染器的paint()方法以在屏幕上显示内容。
绘画可以是全局或增量式(与布局类似):
全局 - 整个树被重新绘制。
增量 - 只有一些渲染器以不影响整个树的方式进行更改。渲染器使其矩形在屏幕上无效。这会导致操作系统将其视为需要重绘和生成绘画事件的区域。操作系统通过将几个区域合并为一个智能方式来完成。
一般来说,了解绘画是一个渐进的过程是很重要的。为了更好的用户体验,渲染引擎会尝试尽快在屏幕上显示内容。它不会等到所有的HTML被解析,才开始构建和布置渲染树。内容的部分内容将被解析并显示,而该过程继续保持来自网络的其余内容项目。
处理脚本和样式表的顺序当解析器到达