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
}
相关推荐
十里-3 小时前
vue.js 2前端开发的项目通过electron打包成exe
前端·vue.js·electron
雨季6664 小时前
构建 OpenHarmony 简易文字行数统计器:用字符串分割实现纯文本结构感知
开发语言·前端·javascript·flutter·ui·dart
雨季6664 小时前
Flutter 三端应用实战:OpenHarmony 简易倒序文本查看器开发指南
开发语言·javascript·flutter·ui
小北方城市网4 小时前
Redis 分布式锁高可用实现:从原理到生产级落地
java·前端·javascript·spring boot·redis·分布式·wpf
console.log('npc')4 小时前
vue2 使用高德接口查询天气
前端·vue.js
2401_892000524 小时前
Flutter for OpenHarmony 猫咪管家App实战 - 添加支出实现
前端·javascript·flutter
天马37984 小时前
Canvas 倾斜矩形绘制波浪效果
开发语言·前端·javascript
天天向上10244 小时前
vue3 实现el-table 部分行不让勾选
前端·javascript·vue.js
qx095 小时前
esm模块与commonjs模块相互调用的方法
开发语言·前端·javascript