转换效果
转换前:
<script setup>
import {ref} from "vue";
let aaa = ref(100);
let bbb = ref(200);
let color = ref('aquamarine');
const vFocus = {
mounted: (el) => el.focus()
}
function changeNumber() {
aaa.value++
}
</script>
<template>
<div>
<div @click="changeNumber" :style="{color: color}">father</div>
<input v-focus>
<div class="list">{{ aaa }} + {{ bbb }}</div>
</div>
</template>
<style scoped>
.list {
height: 40px;
border: 1px solid blue;
background-color: aquamarine;
}
</style>
转换后:
import { createHotContext as __vite__createHotContext } from "/@vite/client";import.meta.hot = __vite__createHotContext("/src/App.vue");import {ref} from "/node_modules/.vite/deps/vue.js?v=f9dcc282";
const _sfc_main = {
__name: 'App',
setup(__props, { expose: __expose }) {
__expose();
let aaa = ref(100);
let bbb = ref(200);
let color = ref('aquamarine');
const vFocus = {
mounted: (el) => el.focus()
}
function changeNumber() {
aaa.value++
}
const __returned__ = { get aaa() { return …mport.meta.hot.accept(mod => {
if (!mod) return
const { default: updated, _rerender_only } = mod
if (_rerender_only) {
__VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render)
} else {
__VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated)
}
})
import _export_sfc from "/@id/__x00__plugin-vue:export-helper"
export default /*#__PURE__*/_export_sfc(_sfc_main, [['render',_sfc_render],['__scopeId',"data-v-7a7a37b1"],['__file',"D:/testone/vite4/vite-vue/vue3-base/src/App.vue"]])
转换过程:
一、.vue文件转换成ast
转换后的结构:
code:.vue文件通过fsp.readFile(file, "utf-8")获取到的字符串,在loadAndTransform这步就获取,parse以code为准解析生成对象结构,即ast
parse:
`parse`:
`baseParse`:
`createRoot`:创建root对象
`parse`:通过this.state状态循环解析code字符串
`stateText`:(state == 1)
`stateBeforeTagName`:(state == 5)
`stateInSFCRootTagName`:(state == 34)
`handleTagName`:通过isEndOfTagSection判断是tag末尾
`onopentagname`:获取标签名(如:script、template等)及相关信息
`stateBeforeAttrName`:
`stateBeforeAttrName`:(state == 11)
`handleAttrStart`:记录属性起点位置
`ondirname`:遇到 @ : . # 自定义指令 时进入,创建相关属性
`stateInAttrName`:(state == 12)
`onattribname`:获取标签内属性(如:setup)
`handleAttrNameEnd`:
`stateAfterAttrName`:
`stateBeforeAttrName`:
`endOpenTag`:
`isVoidTag`:
`stateInRCDATA`:(state == 32)
`fastForwardTo`:快速循环到script结束标签,中间回车位置记录在newlines数组中
`stateInTagName`:(state == 6)
`handleTagName`:获取标签名(如:div)
`stateInDirArg`:(state == 14)
`ondirarg`:在属性对象里创建arg,(如:在解析完@click)
`stateBeforeAttrValue`:(state == 18)
`stateInAttrValueDoubleQuotes`:(state == 19)
`onattribdata`:获取属性绑定字段(如:@click绑定的changeNumber字符串)
`onattribend`:获取属性绑定字段相关属性
`stateInClosingTagName`:(state == 9) 生成标签对象结构(ast)
`onclosetag`:之前在stack栈中存的标签(如:div),现在标签结束将其取出
`stateInDirName`:(state == 13)(自定义指令结束会进入)
`ondirname`:遇到 @ : . # 自定义指令 时进入,创建相关属性
`stateInterpolationClose`:(state == 13)模板语法({{}})结束会进入
`oninterpolation`:生成模板内容(如:aaa)属性对象
`condenseWhitespace`:清除root.children中只有回车的部分,现在只剩script、template、style
二、遍历ast.children生成新文档
`transformMain`:
`createDescriptor`:
const { descriptor, errors } = compiler.parse 转ast过程
descriptor.id = getHash 生成hash值
`genScriptCode`:拼接根据script生成的内容
`resolveScript`:
`compileScript`:
`parse`:根据script内容生成scriptSetupAst或scriptAst
`genTemplateCode`:拼接template内容
`transformTemplateInMain`:
`compile`:
`compileTemplate`:
`doCompileTemplate`:
`compile`:
`genStyleCode`:拼接引入css的路径
......:继续拼接其他字段
相关数据结构:
scriptSetupAst:这里6个对象对应SFC文件script标签中的6条语句\