最近在将一个使用单文件组件OptionsAPI的Vue2JavaScript项目升级到Vue3typescript,利用CompositionAPI。例如下面的选项API方法:exportdefault{props:{name:{type:String,required:true。}},发射:['someEvent','increaseBy']};我们将把它转换成一个组合的API方法:constprops=defineProps<{name:string;}>();constemit=defineEmits<{(event:'someEvent):void;(事件:'increaseBy',值:数字):无效;}>();从选项API的emit和props到组合API的defineemit和defineProps函数的基于类型语法的转换并不简单。我也很好奇Vue是如何处理接口的。TypeScript接口是仅在设计和编译时存在的结构。它们在JavaScript运行时之前被过滤掉,那么它们如何影响组件的行为呢?我想知道是否有办法查看Vue如何解释传递给defineEmits和defineProps的通用参数。如果您注意到文档说您不需要导入defineEmits和defineProps函数。这是因为它们实际上是同名JavaScript函数的宏。Vuewebpack插件使用TypeScript的AST(抽象语法树)在执行完整的TypeScript传递之前推断函数选项的JavaScript版本。如果不是宏:defineProps<{prop1:string;prop2:数字;}>();会变成:defineProps();这将导致缺少参数的错误。如果你查看Vue的SFC(单文件组件)编译器源代码,有一个名为compileScript的函数。我首先尝试使用最少数量的参数调用该函数,这样就不会发生错误,并模拟任何不重要的必要参数。终于找到另一个函数叫parse。这为我提供了我需要的大部分参数,只留下要模拟的组件ID。这是一个小脚本,它采用SFC的.vue文件并输出Vue如何解释TypeScript。从“fs”导入{readFile,writeFile};从“极简主义者”导入parseArgs;从“@vue/compiler-sfc”导入{解析,compileScript};const{file,out}=parseArgs(process.argv.slice(2),{string:["file","out"],别名:{file:"f",out:"o"}});constfilename=file;constmockId="xxxxxxxx";readFile(filename,"utf8",(err,data)=>{const{descriptor}=parse(data,{filename});const{content}=compileScript(descriptor,{inlineTemplate:true,templateOptions:{filename},id:mockId});if(out){writeFile(out,"utf8",content);}else{process.stdout.write(content);}});示例地址:https://stackblitz.com/edit/node-fzuykn?文件=index.js。例如,有以下组件:interfaceBar{prop1:string;prop2:number;}defineProps<{bar:Bar;酒吧:酒吧[];asdf1?:布尔值;asdf2:字符串[];}>();输出:接口栏{prop1:字符串;prop2:number;}exportdefault/*#__PURE__*/_defineComponent({__name:'demo',props:{bar:{type:Object,required:true},bars:{type:Array,required:true},asdf1:{type:Boolean,required:false},asdf2:{type:Array,required:true}},setup(__props:any){return(_ctx:any,_cache:any)=>{return(_openBlock(),_createElementBlock("div"))}}正如您在上面看到的,SFC编译器获取TypeScript类型信息并构建props对象。原始类型是一对一的。接口成为对象,并且?可选语法驱动所需的属性。
