这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
铛铛,这次是我第一次发文,由衷感谢读者,下面我讲的是我对vue3的近期理解
在你执行 npm i vue@next 之后你一定发现了在vue的直属目录下有一个 compiler-sfc,这个文件夹里面的内容主要是能够编译 template,style, script(setup)的字符串,生成对应的内容。
分别对应的是 compileTemplate,compileStyle, compileScript
当然我相信你可能看不懂,是了,我也看不懂,经过我的多方百度,我才知道到这三个方法的使用方式。
你需要通过使用编译 parse 编译一下你所需要解析的字符串生成对应的 AST 树(不知道对不对),后面才是根据对应的树来生成你所需要的render渲染(或者说是可以直接理解的代码)。
parse
相信还是看代码比较直观
import { parse } from 'vue/compiler-sfc'
const parseValue = parse(
`<template><h1>12312312</h1></template>`
,
{
id: 'uid',
filename: 'XX.vue'
}
)
console.log(parseValue)
最后在控制台生成
{
descriptor: {
filename: 'XX.vue',
source: '<template><h1>12312312</h1></template>\n ',
template: {
type: 'template',
content: '<h1>12312312</h1>',
loc: [Object],
attrs: {},
ast: [Object],
map: [Object]
},
script: null,
scriptSetup: null,
styles: [],
customBlocks: [],
cssVars: [],
slotted: false
},
errors: []
}
看,啥都有,但就是啥也不知道干啥的,所以接下来就需要我们的 compileTemplate
compileTemplate
使用上面的数据进行处理
const { code } = compileTemplate({
id: 'XX',
filename: 'XX.vue',
source: parseValue.descriptor.template.content
})
最终你的code 就是你所能认识函数
import { openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("h1", null, "12312312"))
}
有没有感觉很高大上,我所热爱的就是看着自己一步一步从无知变成探索者,我没有在百度上明确的找到上述代码,全都是我看 vue 的 ts 来推测和判断,所以在此,我要感谢 typescript!!! 下面是我完整的代码,执行只要 node 运行文件就行,(别忘记 package.json中type的更改,你需要了解commonjs 和 module)
import { parse, compileTemplate, compileScript } from 'vue/compiler-sfc'
const parseValue = parse(
`
<template><h1>12312312</h1></template>
<script setup>
import { ref } from 'vue'
const name = ref('myName')
</script>
`,
{
id: 'uid',
filename: 'XX.vue'
}
)
const { code } = compileTemplate({
id: 'XX',
filename: 'XX.vue',
source: parseValue.descriptor.template.content
})
const { content } = compileScript(parseValue.descriptor, {
filename: 'XX.vue'
})
console.log(code, content)
控制台中打印
import { openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("h1", null, "12312312"))
} import { ref } from 'vue'
export default {
setup(__props, { expose }) {
expose()
const name = ref('myName')
const __returned__ = { name, ref }
Object.defineProperty(__returned__, '__isScriptSetup', { enumerable: false, value: true })
return __returned__
}
}
这下子总算完成了。是的结束了,有人会问,这有什么用吗?平时干业务会用到吗,我能准确的回答你,用不到,但是可能方便你以后造轮子吧,哈哈。我觉得很强,虽然没看过源码,但是能用出来对我来说就是一大进步。
追更
在你在自己的代码中引入 './XX/xx.vue' 的时候你有没有想过 他为什么能知道 .vue 文件,.vue 文件可不可以变成我们熟知的 .js/ts 能 =) 下面就是我过了一晚上想到的事情,脑子要是好的话,怎么可能隔了一天才知道...
以下就是流程了
-
使用 fs-extra 来获取 .txt/vue 文件的内容,
-
获取文件内容后使用 @vue/compiler-sfc 进行编译 得到 code, content
-
将俩个代码分别存到俩个文件中,分别命名为 indexCode.js, indexContent.js
-
最后参考 vue/compiler-sfc npm 官网上的解说, 最后变成我们所需要的样子
-
上码
indexCode.js
import {
openBlock as _openBlock,
createElementBlock as _createElementBlock,
} from "vue";
export function render(_ctx, _cache) {
return _openBlock(), _createElementBlock("h1", null, "12312312");
}
indexContent.js
import { ref } from "vue";
export default {
setup(__props, { expose }) {
expose();
const name = ref("myName");
const __returned__ = { name, ref };
Object.defineProperty(__returned__, "__isScriptSetup", {
enumerable: false,
value: true,
});
return __returned__;
},
};
index.js
import { render } from "./indexCode";
import script from "./indexContent";
script.render = render;
script.__filename = "XX.vue";
比较
使用方式一个是 './index.vue',另一个是 './App/index.js' 是不是有种非常雄伟的成就感,是的,我有!
其实我最近也有在尝试很多东西,但是都没有怎么实现(更或者说我都不知道怎么实现) 比如我想要一个 使用 esbuild 就能编写的后端代码,因为我想要使用 ts 写,而不需要任何的 egg.js 或者 nest.js。总之我就是觉得人就是要多思考,仅此而已,不管是对是错,亦要尝试。
我虽然写不出来这么优质的代码,但是不能阻止我追赶你们。 尤大 加油