首页 > 编程语言 >vue2源码-五、将模板编译解析成AST语法树2

vue2源码-五、将模板编译解析成AST语法树2

时间:2023-04-15 21:14:27浏览次数:43  
标签:render ast text AST lastIndex 源码 let attrs vue2

生成render函数

  1. 前言

    • 上篇,生成ast语法树,而这篇使用ast语法树生成render函数。
    export function compileToFunction(template) {
      // 1,将模板编译称为 AST 语法树
      let ast = parserHTML(template);
      // 2,使用 AST 生成 render 函数
      let code = codegen(ast);
    }
    
  2. 生成render函数

    codegen方法:根据ast语法树生成render函数。即传入ast语法树,返回render函数。

    function codegen(ast) {
      // 儿子,后面会说
      let children = genChildren(ast.children)
      // 字符串拼接render函数
      let code = `_c('${ast.tag}',${
        ast.attrs.length > 0 ? genProps(ast.attrs) : 'null'
      }${ast.children.length ? `,${children}` : ''})`
      // 返回render函数
      return code
    }
    

    在里面其中有genChildren方法和genProps方法。将分别介绍这两个方法

  3. 处理属性:genProps(ast.attrs)方法

    说明:格式化属性信息。

    // 将属性(attrs)数组格式化为对象
    function genProps(attrs) {
      let str = '' // {name,value}
      for (let i = 0; i < attrs.length; i++) {
        let attr = attrs[i]
        // 如果是style属性
        if (attr.name === 'style') {
          let obj = {}
          // 进行处理
          attr.value.split(';').forEach((item) => {
            let [key, value] = item.split(':')
            obj[key] = value
          })
          attr.value = obj
        }
         // 如果不是,使用JSON.stringify将value转换为字符串
        str += `${attr.name}:${JSON.stringify(attr.value)},`
      }
      // 去掉最后的多余的逗号,并且用{}包裹
      return `{${str.slice(0, -1)}}`
    }
    // _c('div',{id:"app",a:"1",b:"2",style:{"color":" red"}},
    
  4. 处理儿子:genChildren(ast.children)方法

    实现就是进行循环递归:

    function genChildren(children) {
      // 递归孩子
      return children.map((child) => gen(child)).join(',')
    }
    

    其中有一个gen方法,这个方法就是处理儿子的

    直接上代码:

    // 匹配{{xxx}}
    const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g
    function gen(node) {
      // 如果是元素继续递归就好
      if (node.type === 1) {
        return codegen(node)
      } else {
        // 如果不是就是文本类型,对文本进行处理
        let text = node.text
        // 匹配不上,即使普通文本
        if (!defaultTagRE.test(text)) {
          // 包装为_v
          return `_v(${JSON.stringify(text)})`
        } else {
           // 对表达式和普通值执行拼接操作 
          // <div>aaa{{xxx}}</div>
          let tokens = []
          let match
          defaultTagRE.lastIndex = 0
          let lastIndex = 0
          // 执行循环获得结果
           while ((match = defaultTagRE.exec(text))) {
            // 获取当前捕获到的位置
            let index = match.index
            // 说明匹配到了内容,将前一段'<div>aaa '中的 aaa 放入 tokens 数组中
            if (index > lastIndex) {
              tokens.push(JSON.stringify(text.slice(lastIndex, index)))
            }
           // match[1]:表示花括号中间的内容 name,需要处理表达式部分可能存在的换行或回车
            tokens.push(`_s(${match[1].trim()})`)
            // 更新lastIndex,用于下次比对
            lastIndex = index + match[0].length
          }
          // 如果还有剩余的部分要处理
          if (lastIndex < text.length) {
            tokens.push(text.slice(lastIndex))  // 从lastIndex到最后
          }
            // 返回
          return `_v(${tokens.join('+')})`
        }
      }
    }
    

标签:render,ast,text,AST,lastIndex,源码,let,attrs,vue2
From: https://www.cnblogs.com/dgqp/p/17321868.html

相关文章

  • fastdds学习之2——Helloworld Demo
    本节详细介绍了如何使用C++API一步一步地创建一个简单的FastDDS应用程序,其中包含发布者和订阅者。也可以使用eProsimaFastDDSGen工具自行生成与本节中实现的示例类似的示例。在构建发布/订阅应用程序中解释了这种额外的方法,本例程在eProsimaFastDDSGithub仓库中,环境搭建完成......
  • fastdds学习之1——开始
    1、开始这一节定义了DDS和RTPS的概念,也提供了一个逐步讲解的教程,这个教程中讲解了如何开发一个简单的FastDDS发布订阅应用程序。2、什么是DDSDDS是一个以数据为中心的通信一些,主要用在分布式软件的通信领域。它定义了应用程序的通信API和通信语义,这使得数据提供者和数据消费者......
  • fastdds学习之0——简介
    1、fastdds文档eProsimaFastDDS是DDS(DataDistributionService)协议的一个C++语言实现版本,该协议由ObjectManagementGroup(OMG)组织定义。eProsimaFastDDS库既提供了一个应用编程接口(API),又提供了一种通信协议,使用这种通信协议可以部署以数据为中心的发布者-订阅......
  • Stochastic Training of Graph Convolutional Networks with Variance Reduction
    目录概符号说明Motivation本文方法代码ChenJ.,ZhuJ.andSongL.Stochastictrainingofgraphconvolutionalnetworkswithvariancereduction.ICML,2018.概我们都知道,GCN虽然形式简单,但是对于结点个数非常多的情形是不易操作的:多层的卷积之后基本上每个结点......
  • 从零编译 Qt 源码
    写在前头为了保证流程可复现,本文档展示的编译全过程在Windows10提供的沙盒中进行。Linux安装Qt想必都不会有什么问题,所以本文讲的其实是Windows上如何从零编译Qt源码。此处的Qt源码指的是Qt这个第三库本身,所以想找怎么编译自己写的Qt项目的可以到此为止了。......
  • delphi FastReport 从流(数据库)中加载和保存报表
    FastReport从流(数据库)中加载和保存报表属性和方法TfrxReport.LoadFromStreamprocedureLoadFromStream(Stream:TStream);从流中加载报表。参数Stream来源流。TfrxReport.SaveToStreamprocedureSaveToStream(Stream:TStream);将报表保存到流中。参数Stream来源......
  • 亲测一份PHP在线客服系统源码-thinkphp+workerman开发-网上流传最广的客服源码搭建教
    为了帮一个客户修改自己的客服系统,所以把源码在本地搭建了一下。因为,我本身就是使用golang有开发一款客服系统的,本来不愿意看这种旧版本的PHP客服源码。但是客户那边需求很少,购买我的商务版感觉不合算,所以网上找了这一个客服源码,也是流传最广的一款PHP客服系统。当然这个源码有没......
  • 互联网医院源码开发|互联网医院软件如何更加规范化?
    互联网医院系统这几年应用越来越广泛,让患者更好的完成线上就医,线上购药等,其实在诊后的环节中互联网医院更是发挥着真正的作用,因为对于一些慢性病患者来说诊后对患者的管理,后续的用药从医性,才是互联网医院能带给患者真正的环节,互联网医院系统的搭建对各中小型药企也将是一个新渠道,在......
  • 【Spring Cloud】Ribbon工作原理源码剖析
    Ribbon调用流程Ribbon工作原理为什么@LoadBalanced注解能赋予RestTemplate负载均衡的能力?Ribbon组件在启动时,会自动加载RibbonAutoConfiguration这个配置类,如下图RibbonAutoConfiguration加载于EurekaClientAutoConfiguration之前,加载于LoadBalancerAutoConfiguration之后......
  • 源码共读 | axios 工具函数
    前言Axios是一个非常流行的库,它可以让你简单、方便地发送HTTP请求。它可以用在浏览器和node.js中,并且支持跨域请求。在Github上拥有快接近10w颗星了,可见其受欢迎程度。下面就来学习一下axios工具函数的源码。仓库地址:axios/axios:PromisebasedHTTPclientfortheb......