zoukankan      html  css  js  c++  java
  • 了解浏览器接受收 html文件 并渲染的全过程

    有限状态机处理字符

    https://www.cnblogs.com/ssaylo/p/13130138.html ,先看这篇文章,了解 HTTP 请求是如何发送与接收的。

    前言——如何在不适用正则与 JavaScript Api 接口的条件下查找字符数按所在的位置?

    winter 前端进阶训练营第六周

    有限状态机

    • 每一个状态都是一个机器

    • 每一个机器知道下一个状态

      • moore(每个机器都有确定的下一个状态)
      • mealy(根据输入决定下一个状态)(mealy 是个人名,不用去管他)

    使用有限状态机处理字符串

    • v1.0

      // 不用 api,不用正则,写一个 match
      function match(string) {
        for (let c of string) {
          if (c === 'a') {
            return true;
          }
        }
        return false;
      }
      
      match('I m groota');
      
      
    • v2.0

      // 这里会有个问题, "a" 与 "b" 不相邻的时候也会判断为 true,怎么办呢???
      function match(string) {
        let foundA = false;
        for (let c of string) {
          if (c === 'a') {
            foundA = true;
          } else if (foundA && c == 'b') {
            return true;
          }
        }
        return false;
      }
      console.log(match('I acbm groot'));
      
      // 很简单
      function match2(string) {
        let foundA = false;
        for (let c of string) {
          if (c === 'a') {
            foundA = true;
          } else if (foundA && c === 'b') {
            return true;
          } else {
            //////////////////////在这里多加一句话//////////////////////
            foundA = false;
          }
        }
        return false;
      }
      console.log(match2('I acbm groot'));
      
    • v3.0

      // 刚在写的是匹配 a,b 两个变量,那么如果要匹配三个变量呢?如果要匹配四个变量呢?在这里我们就使用到了有限状态机
      // 首先我们定义五个状态,初始值为 false
      // 然后在查找过程找,对状态进行变更
      // 字符串中存在字符,便变更对应的状态为 true
      // 倘若一旦有一个字符不匹配,重置所有的状态
      function match(string) {
        let foundA = false;
        let foundB = false;
        let foundC = false;
        let foundD = false;
        let foundE = false;
        for (let c of string) {
          if (c === 'a') foundA = true;
          else if (foundA && c === 'b') foundB = true;
          else if (foundB && c === 'c') foundC = true;
          else if (foundC && c === 'd') foundD = true;
          else if (foundD && c === 'e') foundE = true;
          else if (foundE && c === 'f') return true;
          else {
            foundA = false;
            foundB = false;
            foundC = false;
            foundD = false;
            foundE = false;
          }
        }
        return false;
      }
      
      console.log(match('I abm groot'));
      console.log(match('I abcdef'));
      
    • v4.0

      // 每个函数就是一个状态
      // 函数参数就是输入
      // 返回的是下一个状态
      function state(input) {
        return next;
      }
      
      function match(string) {
        let state = start;
        for (let c of string) {
          console.log(c);
          state = state(c);
        }
        return state === end;
      }
      
      function start(c) {
        if (c === 'a') return foundA;
        else return start;
      }
      
      function end(c) {
        return end;
      }
      
      function foundA(c) {
        if (c === 'b') return foundB;
        else return start(c);
      }
      
      function foundB(c) {
        if (c === 'c') return end;
        else return start(c);
      }
      
      function foundC(c) {
        if (c === 'd') return foundD;
        else return start(c);
      }
      
      function foundD(c) {
        if (c === 'e') return foundE;
        else return start(c);
      }
      
      function foundE(c) {
        if (c === 'f') return end;
        else return start(c);
      }
      
      console.log(match('aacbc'));
      console.log(match('aacbcdefg'));
      
    • v5.0

      function match(string) {
        let state = start;
        for (let c of string) {
          state = state(c);
        }
        return state === end;
      }
      
      function start(c) {
        if (c === 'a') return foundA;
        else return start;
      }
      
      function end(c) {
        return end;
      }
      
      function foundA(c) {
        if (c === 'b') return foundB;
        else return start;
      }
      
      function foundB(c) {
        if (c === 'c') return foundC;
        else return start;
      }
      
      function foundC(c) {
        if (c === 'a') return foundA2;
        else return start;
      }
      
      function foundA2(c) {
        if (c === 'b') return foundB2;
        else return start;
      }
      
      function foundB2(c) {
        if (c === 'x') return end;
        else if (c === 'c') return foundC;
        else return start;
      }
      
      console.log(match('abcabcabx'));
      
    • 匹配“abababx”

      • 可选: 撞击处理完全未知的pattern

        • 参考: 字符串KMP算法

          (这里先留个坑位了,算法刷完回来解决)

          参考链接

    HTML parser

    第一步: 拆分文件

    • 为了方便文件管理,把parse单独拆到文件中
    • parser接受HTML文本作为参数,返回一颗DOM树
    • 见parse-1.js

    第二步: 创建状态机

    • 使用FSM实现HTML分析
    • 在HTML标签中,已经规定了HTML的状态
    • 见parse-2.js

    第三步: 解析标签

    • 主要的标签有:开始标签,结束标签和自封闭标签
    • 见parse-3.js

    第四步: 创建元素

    • 在状态机中,除了状态迁移,我们还要加入业务逻辑
    • 在标签结束状态提交标签token
    • 见parse-4.js

    第五步: 处理属性

    • 属性值分为单引号、双引号、无引号三种写法,因此需要较多状态处理
    • 处理属性的方式和标签类似
    • 属性结束时,把属性加到标签token上
    • 见parse-5.js

    第六步: 构建DOM树

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

    第七步: 处理文本节点

    • 文本节点与自封闭标签处理类似
    • 多个文本节点需要合并
    • 见parse-7.js

    CSS Computing

    第一步: 收集CSS规则

    • 遇到 style 标签时,我们把 CSS 规则保存起来
    • 我们调用 CSS Parser 来分析 CSS 规则
    • 我们必须要仔细研究此库分析 CSS 规则的格式
    • 见computedCSS-1.js

    第二步: 添加调用

    • 当我们创建一个元素后,立即计算 CSS
    • 理论上,当我们分析一个元素时,所有 CSS 规则已经收集完毕
    • 在真实浏览器中,可能遇到写在 body 的 style 标签,需要重新 CSS 计算的情况,这里我们忽略
    • 见computedCSS-2.js

    第三步: 获取父元素序列

    • 在 computeCss 函数中,我们必须知道元素的所有父元素才能判断元素与规则是否匹配
    • 我们从上一步骤的 stack,可以获取本元素所有的父元素
    • 因为我们首先获取的是”当前元素“,所以我们获得和计算父元素匹配的顺序是从内向外
    • 见computedCSS-3.js

    第四步: 拆分选择器

    • 选择器也要从当前元素从外排列
    • 复杂选择器拆成针对单个元素的选择器,用循环匹配父元素队列
    • 见computedCSS-4.js

    第五步: 计算选择器与元素匹配关系

    • 根据选择器的类型和元素属性,计算是否与当前元素匹配
    • 这里仅实现了三种基本选择器,实际的浏览器中要处理复合选择器
    • 见computedCSS-5.js

    第六步: 生成Computed属性

    • 一旦选择匹配,就应用选择器到元素上,形成 computedStyle
    • 见computedCSS-6.js

    第七步: 确定覆盖关系

    • CSS 规则根据 specificity 和后来优先规则覆盖
    • specificity 是个四元组,越左边权重越高
    • 一个 CSS 规则的 specificity 根据包含的简单选择器相加而成
    • 见computedCSS-7.js
  • 相关阅读:
    Nginx 静态资源缓存设置
    Ubuntu Linux 与 Windows 7双系统安装教程(图文)
    配置可以通过http协议访问的svn服务器
    CentOS下搭建SVN服务器
    LINUX服务器下用root登录ftp
    CentOS 6下编译安装MySQL 5.6
    Jenkins代码管理
    python学习:备份文档并压缩为zip格式
    centos 7 双网卡建网桥脚本实现
    python学习:使用正则收集ip信息
  • 原文地址:https://www.cnblogs.com/ssaylo/p/13139771.html
Copyright © 2011-2022 走看看