天天看点

浏览器构建呈现树的流程

在 Firefox 中,系统会针对 DOM 更新注册展示层,作为侦听器。展示层将框架创建工作委托给 FrameConstructor,由该构造器解析样式并创建框架。

样式计算

构建呈现树时,需要计算每一个呈现对象的可视化属性。这是通过计算每个元素的样式属性来完成的。

样式包括来自各种来源的样式表、inline 样式元素和 HTML 中的可视化属性(例如“bgcolor”属性)。其中后者将经过转化以匹配 CSS 样式属性。

样式表的来源包括浏览器的默认样式表、由网页作者提供的样式表以及由浏览器用户提供的用户样式表(浏览器允许您定义自己喜欢的样式。以 Firefox 为例,用户可以将自己喜欢的样式表放在“Firefox Profile”文件夹下)。

样式计算存在以下难点:

  1. 样式数据是一个超大的结构,存储了无数的样式属性,这可能造成内存问题。
  2. 如果不进行优化,为每一个元素查找匹配的规则会造成性能问题。要为每一个元素遍历整个规则列表来寻找匹配规则,这是一项浩大的工程。选择器会具有很复杂的结构,这就会导致某个匹配过程一开始看起来很可能是正确的,但最终发现其实是徒劳的,必须尝试其他匹配路径。

    例如下面这个组合选择器:

    1

    div

    div

    div

    div

    {

    2

    ...

    3

    }

    这意味着规则适用于作为 3 个 div 元素的子代的 div。如果您要检查规则是否适用于某个指定的 div 元素,应选择树上的一条向上路径进行检查。您可能需要向上遍历节点树,结果发现只有两个 div,而且规则并不适用。然后,您必须尝试树中的其他路径。
  3. 应用规则涉及到相当复杂的层叠规则(用于定义这些规则的层次)。

让我们来看看浏览器是如何处理这些问题的:

共享样式数据

Webkit 节点会引用样式对象 (RenderStyle)。这些对象在某些情况下可以由不同节点共享。这些节点是同级关系,并且:

  1. 这些元素必须处于相同的鼠标状态(例如,不允许其中一个是“:hover”状态,而另一个不是)
  2. 任何元素都没有 ID
  3. 标记名称应匹配
  4. 类属性应匹配
  5. 映射属性的集合必须是完全相同的
  6. 链接状态必须匹配
  7. 焦点状态必须匹配
  8. 任何元素都不应受属性选择器的影响,这里所说的“影响”是指在选择器中的任何位置有任何使用了属性选择器的选择器匹配
  9. 元素中不能有任何 inline 样式属性
  10. 不能使用任何同级选择器。WebCore 在遇到任何同级选择器时,只会引发一个全局开关,并停用整个文档的样式共享(如果存在)。这包括 + 选择器以及 :first-child 和 :last-child 等选择器。

在 Webkit 中,解析样式和创建呈现器的过程称为“附加”。每个 DOM 节点都有一个“attach”方法。附加是同步进行的,将节点插入 DOM 树需要调用新的节点“attach”方法。

处理 html 和 body 标记就会构建呈现树根节点。这个根节点呈现对象对应于 CSS 规范中所说的容器 block,这是最上层的 block,包含了其他所有 block。它的尺寸就是视口,即浏览器窗口显示区域的尺寸。Firefox 称之为 ViewPortFrame ,而 Webkit 称之为 RenderView 。这就是文档所指向的呈现对象。呈现树的其余部分以 DOM 树节点插入的形式来构建。

源引:http://www.nowamagic.net/academy/detail/48110514