toy browser

这篇博客主要是熟悉浏览器的大致工作流程(不涉及代码,代码在最后的链接里)

如上图所示:

  • url回车后,先是解析http
  • 再解析html生成dom树
  • 再解析css
  • 再依据dom和css,进行layout获取position
  • 最后进行render 绘制bitmap

第一步(解析http)

response:

要想解析http 报文,我们可以利用状态机,使用多个状态来区分报文里的每个部分

比如设置一个 WAITTING_STATUS_LINE 状态,在第一个’\n’之前我们都可以视为在 WAITTING_STATUS_LINE 状态,’\n’之后用 WAITTING_STATUS_LINE_END 表示status line 的部分结束,以此类推使用各个状态来筛选响应报文的内容

这样我们就可以拿到response body 里面的html文本

第二步,解析html生成dom树

要想利用html文本最后返回一颗dom树,还是创建状态机来实现,其实html规范里面已经定义了很多很多个状态了,我们只选取一些 状态来模拟一下大致过程,'<‘表示 tagOpen ,在tagOpen之后就是tagName如果后面有个空格后面又有字符串那就是 attributeName 紧跟着’=’,后面就是 attributeValue,简而言之就是分析每一个token,找到每一个token所表达的语义

最后获得多个平级的对象,这个对象如下图结构

接下来就是如何把同级对象构建成一颗dom树

  • 从标签构建DOM树的基本技巧是使用栈
  • 遇到开始标签时创建元素并入栈,遇到结束标签时出栈
  • 自封闭节点可视为入栈后立刻出栈
  • 任何元素的父元素是它入栈前的栈顶

如此操作之后会获得如下图包含children的一个树结构(ast)

第三步 给每个dom树节点匹配对应的css rules

首先利用css库将<style>里的css表达式转换成css rules(其实现方式也是利用状态机生成ast),rule结构如下,declartions里面包含了css属性名和属性值,

然后根据当前的css rule的 selectors以及它的parent 的selectors 和第二步我们获得dom树进行比对,得到当前的css rule 应该添加到哪一个元素上,把这些css rule 添加到元素的computedStyle属性上

第四步 进行layout 计算每个元素在坐标轴上的位置

首先我们需要抽象出一个坐标轴

主轴:mainSize, mainStart, mainEnd, mainSign, mainBase,       

交叉轴:  crossSize, crossStart, crossEnd, crossSign, crossBase

例如flex布局中的 flexDirection === ‘row’ ,那么上面的变量就是如此:

        mainSize = 'width';
        mainStart = 'left';
        mainEnd = 'right';
        mainSign = +1;
        mainBase = 0;

        crossSize = 'height';
        crossStart = 'top';
        crossEnd = 'bottom'

然后把每个元素放入一行(行可以用数组实现)根据主轴的尺寸和css规则判断换不换行,再计算交叉轴的高度(取每一行的元素的最高交叉轴尺寸),获得每个元素在坐标轴上的坐标表示,如element[mainSize],element[crossSize]的具体数值

第五步根据坐标点render进行绘制

这里使用images库( Node.js轻量级跨平台图像编解码库 ),把上面的元素传入images的绘制方法就可以了,循环调用子元素的绘制方法完成dom树的 绘制(这里没有实现文字的绘制和图层的一些处理)

完整的代码地址: https://github.com/dz333333/Frontend-01-Template/tree/master/week07/layout

发表评论

您的电子邮箱地址不会被公开。