37-mini-vue 解析插值

实现解析插值功能

  1. 我们创建目录并写好测试文件
js 复制代码
import {
    baseParse
} from '../src/parse'
describe("Parse", () => {
    describe("interpolation", () => {
        test('simple interpolation', () => {
            const ast = baseParse("{{message}}")
            // root ast 是整棵树的根节点
            expect(ast.children[0]).toStrictEqual({ // 希望的结构
                type: "interpolation",
                content: {
                    type: "simple_expression",
                    content: "message"
                }
            })
        })
    })
})
  1. 我们简单写一个 baseParse 函数,直接返回我们希望的解构,先让测试不报错
js 复制代码
// compiler-core/src/parse.ts
export function baseParse() {
    return [{ // 希望的结构
        type: "interpolation",
        content: {
            type: "simple_expression",
            content: "message"
        }
    }]
}
  1. 测试已经通过,我们对 baseParse 函数进一步处理
js 复制代码
// 1. 我们对传入的参数进行处理 ✅
export function baseParse(content: string) {
  const context = createParseContext(content) // 将数据放在对象中,方便处理

  // 2. 这里对返回值进行处理 ✅
  return createRoot([
    {
      type: "interpolation",
      content: {
        type: "simple_expression",
        content: "message"
      }
    }
  ])
}

/**
 * 本来直接返回,这里返回一个函数,函数内返回原来的值,方便对返回值,进行一些处理
 * @param content 
 * @returns 
 */
function createParseContext(content) {
  return {
    source: content
  }
}

function createRoot(children) {
  return {
    children
  }
}
  1. 我们已经对现有的函数和数据进行了抽离,我们想要对单条返回对象进行一些操作,于是我们对这里的
    返回值做进一步的处理
js 复制代码
export function baseParse(content: string) {
  const context = createParseContext(content) 
  // 我们将这里传入的参数,再次传入一个函数
  return createRoot(parseChildren(context))
}
// 这里将每条对象数据放入数组中
function parseChildren(context) {
  const nodes: any[] = []
  let node:any
  if(context.source.startsWith('{{')) {
     node = parseInterpolation(context)
  }
  nodes.push(node)
  return nodes
}
// 这里将每条对象数据进行处理
function parseInterpolation(context) {
  return {
    type: "interpolation",
      content: {
      type: "simple_expression",
        content: "message"
    }
  }
}
  1. 我们现在对每条对象数据进行处理
js 复制代码
function parseInterpolation(context) {
  // 插值语法的分隔符
  const openDelimiter = "{{"
  const closeDelimiter = "}}"
  // }} 的下标
  const closeIndex = context.source.indexOf(closeDelimiter, openDelimiter.length)
  /* 将内容向后推, 取 {{ 后面的数据  */
  advanceBy(context, openDelimiter.length)
  // 内容的长度
  const rawContentLength = closeIndex - openDelimiter.length
  // 截取内容 
  const rawContent = context.source.slice(0, rawContentLength)
  // 去掉空格
  const content = rawContent.trim()
  // 插值语法后面拼接的字符串
  advanceBy(context, rawContentLength + closeDelimiter.length)

  return {
    type: NodeTypes.INTERPOLATION, // 这里对一些类型抽离
    content: {
      type: NodeTypes.SIMPLE_EXPRESSION,
      content
    }
  }
}

function advanceBy(context: any, length: number) {
  context.source = context.source.slice(length)
}
// compiler-core/src/ast.ts 类型抽离
export const enum NodeTypes {
  INTERPOLATION,
  SIMPLE_EXPRESSION
}
相关推荐
ZC跨境爬虫7 小时前
跟着 MDN 学 HTML day_9:(信件语义标记)
前端·css·笔记·ui·html
前端老石人7 小时前
HTML 字符引用完全指南
开发语言·前端·html
matlab_xiaowang7 小时前
Redux 入门:JavaScript 可预测状态管理库
开发语言·javascript·其他·ecmascript
幼儿园技术家7 小时前
前端如何设计权限系统(RBAC / ABAC)?
前端
前端摸鱼匠9 小时前
Vue 3 的v-bind合并行为:讲解v-bind与普通属性合并的规则
前端·javascript·vue.js·前端框架·ecmascript
REDcker9 小时前
浏览器端Web程序性能分析与优化实战 DevTools指标与工程清单
开发语言·前端·javascript·vue·ecmascript·php·js
donecoding11 小时前
一个 sudo 引发的血案:npm 全局包权限错乱彻底修复
前端·node.js·前端工程化
风骏时光牛马11 小时前
Raku正则匹配与数据批量处理实操案例
前端
nbwenren11 小时前
2026实测:Gemini 3 镜像站视觉能力实践——拍照原型图,一键生成 HTML+CSS 代码
前端·css·html
Lee川11 小时前
Prisma 实战指南:像搭积木一样设计古诗词数据库
前端·数据库·后端