Vite 全局组件的自动批量化注册

68 阅读1分钟

一、目录结构

|-src
|  |-components
|    |-Pagination
|      |-index.vue
|    |-QrCode
|      |-index.vue
|    |-index.ts                       # 自动化导入逻辑
|  |-main.ts                          # 项目的入口文件
|-types
|  |-global-components.d.ts           # 全局组件的类型 提供 TypeScript 提示
|-tsconfig.json

二、自动导入流程

src/components/index.ts

import { defineAsyncComponent, AsyncComponentLoader } from 'vue'
import type { App } from 'vue'

/** 获取所有组件,该方法返回一个对象 */
const components = import.meta.glob('./**/index.vue')

export default {
  install(app: App<any>) {
    // 遍历对象并注册异步组件
    for (const [key, value] of Object.entries(components)) {
      const name = key.split('/')[1]
      app.component(name, defineAsyncComponent(value as AsyncComponentLoader))
    }
  },
}

三、注册全局组件

这里利用 Vue 的 Plugin 特性在 main.ts 进行注册

import { createApp } from 'vue'
import router from './router' // 路由
import App from './App.vue' // 全局唯一根组件
import registerGlobalComponents from '@/components' // 批量自动化注册全局组件

async function bootstrap() {
  const app = createApp(App)
  
  /** 批量自动化注册全局组件 */
  app.use(registerGlobalComponents)
  
  app.use(router)
  await router.isReady()
  app.mount('#app')
}

bootstrap()

四、配置组件的类型声明

类型文件 types/global-components.d.ts

export {}

declare module 'vue' {
  export interface GlobalComponents {
    Pagination: typeof import('../src/components/Pagination/index.vue')['default']
    QrCode: typeof import('../src/components/QrCode/index.vue')['default']
  }
}

五、tsconfig.json

{
  // 定义希望被编译的文件所在的目录 ** 代表任意目录 * 代表任意文件
  "include": ["types/**/*.d.ts"]
}

六、后记

  • components 下一个组件一个文件夹,index.vue 作为其入口
  • unplugin-vue-componentsdirs 在某种程度上也可以提供自动导入的功能
  • 后者受控较浅 诸君自行权衡利弊