资讯专栏INFORMATION COLUMN

浏览器渲染的那些事(二)

MadPecker / 1851人阅读

摘要:接上一篇浏览器渲染的那些事一继续说。哈希表的选择器各不相同,包括,标记名称等。例如,如果选择器是,就把规则放入的哈希表中还有一种通用哈希表,适合不属于上述类别的规则。

接上一篇浏览器渲染的那些事(一)继续说。

构建呈现树 Render Tree/Frame Tree 渲染的流程:

在这部分我们来讲一下构建Render Tree的过程。
呈现树主要是负责布局并将自身及其子元素绘制出来。
Webkits RenderObject类是所有呈现器的基类。定义如下:

class RenderObject{
    virtual void layout();
    virtual void paint(PaintInfo);
    virtual void rect repeatRect();
    Node* node; //DOM node
    RenderStyle* style; //the computed style
    RenderLayer* containgLayer; //the 
}

每个呈现器都代表了一个矩形区域,一般对应于相关节点的css框,包含宽度、高度、位置等几何信息。
不过对于一些具有复杂结构的元素,就对应了几个可见对象,这就不是一个矩形能表现出来的了。例如select元素【对应一个显示区域,一个下拉列表以及一个按钮】。
不规范的html也会产生多个渲染对象。【css规范中,一个行内元素只能仅包含行内元素或仅包含块状元素,在存在混合内容时,将会创建匿名的块状渲染对象包裹住行内元素。】

呈现树与DOM树关系

呈现树与DOM元素相对应,但不是一一对应。
非可视化的DOM元素就不会插入呈现树,例如head元素。
display为"none"的元素也不会显示在呈现树中【visibility:hidden的元素仍会显示】

除此之外,一些渲染对象和其对应的DOM节点不是在树上的位置也有所不同。
例如浮动元素和绝对定位元素在文本流之外,那么呈现树会标识出真实的结构,并用一个占位结构标识出它们原先的位置。

webkit代码中说明了如何根据display属性决定某个节点创建什么对象的渲染对象。

RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
{
    Document* doc = node->document();
    RenderArena* arena = doc->renderArena();
    ...
    RederObject* o = 0;
    
    switch(style->display()){
        case NONE:
            break;
        case INLINE:
            o = new (arena) RenderInline(node);
            break;
        case BLOCK:
            o = new (arena) RenderBlock(node);
            break;
        ...
    }    
    return o;
}
样式处理

构建呈现树的时候,需要计算每一个呈现对象的可视化属性,也就是计算每个元素的样式属性来完成。这部分比较繁琐。有的部分是我自己翻译理解的【如果有误请指出,谢谢】

样式计算的复杂性
样式计算是个复杂的工程,首先存储了无数的样式属性,可能会造成内存问题;如果没有进行优化,那么为每个元素查找匹配的规则都需要遍历一遍规则列表,而且选择器的结构可能会造成走错匹配路径。除此之外,应用规则也有复杂的层叠规则。【!important需要创建一个额外的规则对象 CSSImportantRule】

webkit内核浏览器的处理方案
webkit有样式对象,直接把这个style对象存在对应的DOM结点上。因此会对匹配的声明遍历4次,首先应用非重要高优先级的属性,其次是高优先级重要规则,然后是普通优先级非重要规则,最后是普通优先级重要规则。多次出现的属性会根据正确的层叠顺序进行解析,最后出现的最终生效。

firefox的处理方案
firefox采用了规则树样式上下文树来简化样式计算。

规则树包含了所有已经知道规则匹配的路径。

在计算某个特定元素的样式上下文时,先计算规则树中的对应路径,或使用现有路径,从路径中最高优先级的底层节点开始,向上遍历规则树,直到在新的样式上下文中结构填充完成。也就是css优先级。(在之前写的css选择器中有讲到。)【规则树只有当某个节点样式需要计算时,才会添加新的计算路径。不会在开始时候就为所有节点进行计算】。

如果没有满足这个元素的样式,对于inherit的属性就会使用initial value【例如"font-size","color"】,对于reset类型的属性就使用默认值【例如"border","background"】

css rule processor处理方式

css rule processor会将所有规则按照级联顺序排序,然后放入RuleHash。哈希表的选择器各不相同,包括ID,class,标记名称等。【例如,如果选择器是ID,就把规则放入ID的哈希表中】还有一种通用哈希表,适合不属于上述类别的规则。匹配样式时,就在RuleHash"s table查找,然后合并已经保存的样式列表,然后SelectorMatchesTree 会去找真正匹配的那个选择器。

【查找id和class的速度比属性选择器快得多!】

对于伪元素,是保存在一个元素hash内,所以查找伪元素只需要查找一个哈希表。
有点难理解,看个栗子【来自MDN】。

//HTML代码

   A few quotes
   
       Franklin said that 
       "A penny saved is a penny earned."
   
   
       FDR said 
       "We have nothing tofear but 
           fear itself."
       
   


//css样式如下
/ rule 1 / doc { display: block; text-indent: 1em; }

/* rule 2 */ title { display: block; font-size: 3em; }
/* rule 3 */ para { display: block; }
/* rule 4 */ [class="emph"] { font-style: italic; }
       

Rule tree规则树如下:

Style context tree样式上下文树如下:

4.匹配规则顺序
前面有说到样式对象的属性,如果定义有多个,那么就需要通过层叠顺序来决定最终的显示效果。

层叠顺序优先级由高到低:
用户重要声明>作者重要声明>作者普通声明>用户普通声明>浏览器声明

选择器的优先级呢,可以看我之前写的css选择器总结

规则排序
匹配段规则会根据级联顺序进行排序。webkit对于较小列表使用冒泡排序,对于较大的列表使用归并排序。

参考文献:

浏览器内部工作原理

浏览器的渲染原理简介

How browsers work

有关网页渲染,每个前端开发者都该知道的那点事

前端文摘:深入解析浏览器的幕后工作原理

MDN:Style System Overview

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/115262.html

相关文章

  • 览器渲染那些

    摘要:接上一篇浏览器渲染的那些事一继续说。哈希表的选择器各不相同,包括,标记名称等。例如,如果选择器是,就把规则放入的哈希表中还有一种通用哈希表,适合不属于上述类别的规则。 接上一篇浏览器渲染的那些事(一)继续说。 构建呈现树 Render Tree/Frame Tree 渲染的流程: 在这部分我们来讲一下构建Render Tree的过程。呈现树主要是负责布局并将自身及其子元素绘制出来。We...

    沈建明 评论0 收藏0
  • 览器渲染那些

    摘要:接上一篇浏览器渲染的那些事一继续说。哈希表的选择器各不相同,包括,标记名称等。例如,如果选择器是,就把规则放入的哈希表中还有一种通用哈希表,适合不属于上述类别的规则。 接上一篇浏览器渲染的那些事(一)继续说。 构建呈现树 Render Tree/Frame Tree 渲染的流程: 在这部分我们来讲一下构建Render Tree的过程。呈现树主要是负责布局并将自身及其子元素绘制出来。We...

    Crazy_Coder 评论0 收藏0
  • JS异步那些 五 (异步脚本加载)

    摘要:遵循的是异步模块定义规范,遵循的是通用模块定义规范。不同的脚本加载这个模块,得到的都是同一个实例。关于异步那些事就写到这里了,很多地方理解的不够深刻希望大家多多指教。 JS异步那些事 一 (基础知识)JS异步那些事 二 (分布式事件)JS异步那些事 三 (Promise)JS异步那些事 四(HTML 5 Web Workers)JS异步那些事 五 (异步脚本加载) 异步脚本加载 阻塞性...

    terasum 评论0 收藏0
  • 前端计划——JavaScript中关于setTimeout那些

    摘要:需要注意的是,及更早的浏览器不支持第一种语法中向延迟函数传递额外参数的功能。如果在不改变递归模式的前提下修善这段代码解决方案加入定时器题目四考察和系列解释立即的对象,是在本轮事件循环的结束时,而不是在下一轮事件循环的开始时。 前言:setTimeout是JavaScript中常见的一个window对象方法,本文将介绍关于它的一些基础知识和易出错的地方。 1、基础知识 作用:setTim...

    sihai 评论0 收藏0
  • 览器渲染那些之 Reflow、Repaint

    摘要:原文链接浏览器渲染那些事之浏览器内核渲染引擎在各个浏览器厂商你追我赶的形势下,截止今日,产生了很多不同的浏览器,各个浏览器本质大同小异,核心部分基本相似,由渲染引擎和引擎组成。 原文链接 浏览器渲染那些事之 Reflow、Repaint 浏览器内核(渲染引擎) 在各个浏览器厂商你追我赶的形势下,截止今日,产生了很多不同的浏览器,各个浏览器本质大同小异,核心部分基本相似,由渲染引擎和 J...

    morgan 评论0 收藏0

发表评论

0条评论

MadPecker

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<