import.meta.glob
的各种实用场景和详细示例如下:
1. Vue 组件自动注册系统
typescript
// components/index.ts
const components = import.meta.glob('./**/*.vue', { eager: true })
export function registerGlobalComponents(app) {
Object.entries(components).forEach(([path, module]) => {
// 提取组件名称
// 例如:'./Button/index.vue' -> 'Button'
// './Form/Input.vue' -> 'FormInput'
const componentName = path
.split('/')
.filter(segment => segment !== '.' && !segment.includes('.vue'))
.join('')
app.component(componentName, module.default)
})
}
// 使用
import { createApp } from 'vue'
import { registerGlobalComponents } from './components'
const app = createApp(App)
registerGlobalComponents(app)
2. 高级路由配置系统
typescript
// router/index.ts
const layouts = import.meta.glob('../layouts/*.vue', { eager: true })
const pages = import.meta.glob('../pages/**/*.vue')
// 处理布局组件
const layoutComponents = Object.entries(layouts).reduce((acc, [path, module]) => {
const layoutName = path.match(/\.\.\/layouts\/(.*)\.vue$/)?.[1]
if (layoutName) {
acc[layoutName] = module.default
}
return acc
}, {})
// 生成路由配置
const routes = Object.entries(pages).map(([path, component]) => {
// 从文件路径提取路由信息
const routePath = path
.replace('../pages', '')
.replace('.vue', '')
.replace(/\/index$/, '/')
// 从文件名提取元数据
const segments = path.split('/')
const fileName = segments[segments.length - 1].replace('.vue', '')
// 判断是否需要认证(例如:文件名以 Auth 开头)
const requiresAuth = fileName.startsWith('Auth')
// 确定使用的布局(可以基于目录结构)
const layout = segments.includes('admin') ? 'AdminLayout' : 'DefaultLayout'
return {
path: routePath,
component,
meta: {
requiresAuth,
layout: layoutComponents[layout]
}
}
})
3. 多语言国际化系统
typescript
// i18n/index.ts
const messages = import.meta.glob('./locales/**/*.json', {
eager: true,
as: 'string'
})
interface LocaleMessages {
[locale: string]: {
[key: string]: any
}
}
// 处理语言文件
const i18nMessages: LocaleMessages = Object.entries(messages).reduce((acc, [path, content]) => {
// 提取语言代码和命名空间
// 例如:./locales/zh-CN/common.json -> { locale: 'zh-CN', namespace: 'common' }
const match = path.match(/\.\/locales\/([^/]+)\/([^.]+)\.json$/)
if (match) {
const [, locale, namespace] = match
if (!acc[locale]) {
acc[locale] = {}
}
// 解析 JSON 内容并按命名空间存储
acc[locale][namespace] = JSON.parse(content)
}
return acc
}, {})
// 创建 i18n 实例
import { createI18n } from 'vue-i18n'
export const i18n = createI18n({
messages: i18nMessages,
legacy: false,
locale: 'zh-CN',
fallbackLocale: 'en'
})
4. 动态 API 接口管理
typescript
// api/index.ts
const apiModules = import.meta.glob('./modules/*.ts', { eager: true })
interface ApiDefinition {
path: string
method: 'GET' | 'POST' | 'PUT' | 'DELETE'
auth?: boolean
}
// 收集所有 API 定义
const apiDefinitions = Object.entries(apiModules).reduce((acc, [path, module]) => {
const namespace = path.match(/\.\/modules\/(.*)\.ts$/)?.[1]
if (namespace) {
acc[namespace] = module.default
}
return acc
}, {})
// 创建请求实例
import axios from 'axios'
const instance = axios.create({
baseURL: '/api'
})
// 生成 API 方法
export const api = Object.entries(apiDefinitions).reduce((acc, [namespace, definitions]) => {
acc[namespace] = {}
Object.entries(definitions).forEach(([key, def]: [string, ApiDefinition]) => {
acc[namespace][key] = async (data?: any) => {
const config = {
url: def.path,
method: def.method,
...(def.method === 'GET' ? { params: data } : { data })
}
if (def.auth) {
// 添加认证信息
config.headers = {
Authorization: `Bearer ${localStorage.getItem('token')}`
}
}
return instance(config)
}
})
return acc
}, {})
5. 自动加载 Vuex/Pinia 模块
typescript
// store/index.ts
const storeModules = import.meta.glob('./modules/*.ts', { eager: true })
// Vuex 示例
import { createStore } from 'vuex'
const modules = Object.entries(storeModules).reduce((acc, [path, module]) => {
const moduleName = path.match(/\.\/modules\/(.*)\.ts$/)?.[1]
if (moduleName) {
acc[moduleName] = module.default
}
return acc
}, {})
export const store = createStore({
modules
})
// Pinia 示例
const stores = Object.entries(storeModules).reduce((acc, [path, module]) => {
const storeName = path.match(/\.\/modules\/(.*)\.ts$/)?.[1]
if (storeName) {
acc[storeName] = module.default
}
return acc
}, {})
// 自动注册 store
export function registerStores(app) {
const pinia = createPinia()
app.use(pinia)
Object.entries(stores).forEach(([name, store]) => {
pinia.use(store)
})
}
6. 自动注册指令系统
typescript
// directives/index.ts
const directives = import.meta.glob('./modules/*.ts', { eager: true })
export function registerDirectives(app) {
Object.entries(directives).forEach(([path, module]) => {
const directiveName = path.match(/\.\/modules\/(.*)\.ts$/)?.[1]
if (directiveName) {
// 转换指令名称为 kebab-case
// 例如:clickOutside -> v-click-outside
const kebabName = directiveName
.replace(/([A-Z])/g, '-$1')
.toLowerCase()
.replace(/^-/, '')
app.directive(kebabName, module.default)
}
})
}
这些示例展示了 import.meta.glob
在实际项目中的高级应用。每个示例都包含了:
- 文件组织结构的建议
- 命名规范的处理
- 类型安全的考虑
- 实际业务场景的适配
通过这些模式,可以构建出更加模块化、可维护的项目结构。