实现例子
element
类型 的 codegen
跟官网的不一样,官网的是优化版的,我们这只实现核心功能。
<div></div>
// 生成为
const { createElementVNode: _createElementVNode } = Vue
export function render(_ctx, _cache) { return _createElementVNode(
'div') }
测试样例
import { transformElement } from "../src/transforms/transformElement";
test("simple element", () => {
const template = "<div></div>";
const ast = baseParse(template);
transform(ast, {
// 加入处理插件
nodeTransforms: [transformElement],
});
const code = codegen(ast);
expect(code).toMatchSnapshot();
});
实现
新增 transformElement plugin
transformElement
里面主要是帮我们把 element
对应的 hepler
添加进去
/*
* @Author: Lin ZeFan
* @Date: 2022-04-10 10:45:42
* @LastEditTime: 2022-04-17 13:16:34
* @LastEditors: Lin ZeFan
* @Description:
* @FilePath: \mini-vue3\src\compiler-core\src\transforms\transformElement.ts
*
*/
import { NodeType } from "../ast";
import { CREATE_ELEMENT_VNODE } from "../runtimeHelpers";
export function transformElement(node, context) {
if (node.type === NodeType.ELEMENT) {
context.helper(CREATE_ELEMENT_VNODE);
}
}
这里引用了 context.hepler,我们前面调用 plugin
的时候没有把对应的context传过来,所以要优化一下
function traverseNode(node, context) {
const { nodeTransforms } = context;
for (let index = 0; index < nodeTransforms.length; index++) {
const transform = nodeTransforms[index];
+ transform(node, context);
}
// 在这里遍历整棵树的时候,将根据不同的 node 的类型存入不同的 helper
switch (node.type) {
case NodeType.INTERPOLATION:
context.helper(TO_DISPLAY_STRING);
break;
case NodeType.ROOT:
case NodeType.ELEMENT:
// 只有在 ROOT 和 ELEMENT 才会存在 children
traverseChildren(node, context);
break;
default:
break;
}
}
新增 element helper
export const TO_DISPLAY_STRING = Symbol('toDisplayString')
// 加入 createElementVNode
export const CREATE_ELEMENT_VNODE = Symbol('createElementVNode')
export const HelperNameMapping = {
[TO_DISPLAY_STRING]: 'toDisplayString',
[CREATE_ELEMENT_VNODE]: 'createElementVNode',
}
判断 element
类型
最后在 codegen 阶段加入对于 element 的处理。
function genNode(node, context) {
switch (node.type) {
case NodeType.TEXT:
genText(node, context)
break
case NodeType.INTERPOLATION:
genInterpolation(node, context)
break
case NodeType.SIMPLE_EXPRESSION:
genExpression(node, context)
break
// 加入对 element 的处理
case NodeType.ELEMENT:
genElement(node, context)
break
}
}
function genElement(node, context) {
const { push } = context;
const { tag } = node;
push(`${helper(CREATE_ELEMENT_VNODE)}('${tag}')`);
}