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
}
相关推荐
JAVA面经实录9171 分钟前
前端系统化学习计划表(含完整知识思维导图)
前端·学习
本末倒置18316 分钟前
开发了一个所见所得的md编辑器,致敬Typora大佬
前端
kyriewen34 分钟前
TypeScript 高级类型:我用 infer 写了一个类型安全的 EventBus,终于搞懂了泛型约束
前端·javascript·typescript
UXbot1 小时前
原型设计工具如何帮助新人快速进入产品行业?
前端·低代码·ui·交互·团队开发·原型模式·web app
黄敬峰2 小时前
从 DFS 遍历到抖音推荐算法:前端工程师的硬核复习笔记
前端
zach2 小时前
网页中的虚拟滚动技术是不是源自IOS中的tableview的机制
前端
林希_Rachel_傻希希2 小时前
1小时速通React之Hooks
前端·javascript·面试
柯克七七2 小时前
公司前端项目打包体积从 2MB 降到 400KB,我改了这四个配置
前端
英勇无比的消炎药2 小时前
我才发现这些架构的“拆”与“合”哲学
前端