实现解析插值功能
- 我们创建目录并写好测试文件
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"
}
})
})
})
})
- 我们简单写一个 baseParse 函数,直接返回我们希望的解构,先让测试不报错
js
// compiler-core/src/parse.ts
export function baseParse() {
return [{ // 希望的结构
type: "interpolation",
content: {
type: "simple_expression",
content: "message"
}
}]
}
- 测试已经通过,我们对 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
}
}
- 我们已经对现有的函数和数据进行了抽离,我们想要对单条返回对象进行一些操作,于是我们对这里的
返回值做进一步的处理
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"
}
}
}
- 我们现在对每条对象数据进行处理
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
}