如何用TypeScript和Vite动态导出Vue3组件?
解决Vite+TypeScript动态导出Vue组件的问题
问题原因
你当前的代码用export default导出了一个包含所有组件的对象,但import { MyButton }是在查找具名导出,而非默认导出对象里的属性,因此会抛出导出不存在的错误。
解决方案1:实现动态具名导出(支持解构导入)
通过动态挂载组件到模块的exports对象上,实现和静态导出一致的效果:
// my-components/index.ts const modules = import.meta.glob('./src/*.vue', { eager: true }) Object.entries(modules).forEach(([path, module]) => { // 从文件路径提取组件名(比如 "./src/MyButton.vue" → "MyButton") const componentName = path.match(/\/([^/]+)\.vue$/)?.[1] || '' // 若组件内通过defineOptions声明了name,也可优先用__name(需Vue 3.3+) // const componentName = (module as { default: { __name: string } }).default.__name if (componentName) { (module.exports as any)[componentName] = (module as { default: any }).default } }) // 可选:添加TypeScript类型提示 export type ComponentExports = { [K in keyof typeof modules as K extends `./src/${infer Name}.vue` ? Name : never]: typeof modules[K]['default'] } declare module '*.vue' { import type { DefineComponent } from 'vue' const component: DefineComponent<{}, {}, any> export default component }
使用方式和你预期一致:
<script setup lang="ts"> import { MyButton, MyInput } from '@/components/my-components' </script>
解决方案2:默认导出对象(调整导入逻辑)
如果不想修改导出逻辑,可保持默认导出,调整导入方式即可:
// my-components/index.ts const modules: Record<string, any> = import.meta.glob('./src/*.vue', { eager: true }) const exportData: Record<string, any> = {}; Object.keys(modules).forEach(component => { // 优先用组件声明的__name,否则从路径提取 const name = modules[component].default.__name || component.replace(/^\.\/src\/(.*)\.vue$/, '$1') exportData[name] = modules[component].default }) export default exportData
导入时解构默认导出的对象:
<script setup lang="ts"> import Components from '@/components/my-components' const { MyButton, MyInput } = Components </script>
注意事项
- 若使用组件的
__name属性,在<script setup>中需通过defineOptions显式声明组件名(Vue 3.3+支持):<script setup lang="ts"> defineOptions({ name: 'MyButton' }) </script> import.meta.glob的eager: true必须添加,否则组件会被懒加载,无法立即导出。
内容的提问来源于stack exchange,提问作者Gerard
相关产品推荐
相关产品推荐

