以下详细介绍 import.meta.glob
的使用:
1. 参数详解
import.meta.glob(
pattern, // 匹配模式:字符串或字符串数组
{
eager?: boolean, // 是否同步导入
import?: string | string[], // 指定导入的内容
query?: string|Record<string, string | number | boolean> // 查询参数
}
)
2. 基础示例(带详细注释)
// 1. 基本异步导入
const modules = import.meta.glob('./modules/*.ts')
async function loadModules() {
// 遍历所有匹配的模块
for (const path in modules) {
// 等待模块加载完成
const module = await modules[path]()
// 输出模块路径和内容
console.log('模块路径:', path)
console.log('模块内容:', module)
}
}
// 2. 同步导入(eager 模式)
const eagerModules = import.meta.glob('./modules/*.ts', {
eager: true // 设置为 true 表示同步导入
})
// 3. 导入特定内容
const specificImports = import.meta.glob('./components/*.vue', {
import: 'default', // 只导入默认导出
eager: true
})
// 4. 多种导入内容
const multipleImports = import.meta.glob('./components/*.vue', {
import: ['default', 'setup'], // 导入多个指定内容
eager: true
})
// 5. 以 URL 形式导入
const imageUrls = import.meta.glob('./assets/*.png', {
query: '?url' // 作为 URL 导入
})
// 6. 导入原始内容
const rawContents = import.meta.glob('./files/*.md', {
query: '?raw' // 作为原始文本导入
})
// 7. 多模式匹配
const multiPattern = import.meta.glob([
'./components/**/*.vue', // 匹配所有子目录的 Vue 文件
'!./components/ignored/*.vue' // 排除特定目录
])
3. 实际使用场景
场景一:动态组件加载系统
// components/loader.ts
// 定义组件模块的类型
interface ComponentModule {
default: any; // Vue 组件
meta?: {
name: string;
version: string;
}
}
// 导入所有组件
const componentModules = import.meta.glob<ComponentModule>('./*/index.vue')
export class ComponentLoader {
// 存储已加载的组件
private loadedComponents: Map<string, any> = new Map()
// 加载组件
async loadComponent(name: string): Promise<any> {
// 构建组件路径
const componentPath = `./${name}/index.vue`
// 检查组件是否存在
if (!componentModules[componentPath]) {
throw new Error(`组件 ${name} 不存在`)
}
// 检查是否已加载
if (this.loadedComponents.has(name)) {
return this.loadedComponents.get(name)
}
try {
// 加载组件
const module = await componentModules[componentPath]()
// 存储组件
this.loadedComponents.set(name, module.default)
return module.default
} catch (error) {
throw new Error(`加载组件 ${name} 失败: ${error.message}`)
}
}
}
场景二:多语言文件管理系统
// i18n/loader.ts
// 定义语言包类型
interface LocaleMessages {
[key: string]: any;
}
// 导入所有语言文件
const localeFiles = import.meta.glob('./locales/**/*.json', {
eager: true // 同步导入
})
export class I18nLoader {
// 存储语言包
private messages: Record<string, LocaleMessages> = {}
constructor() {
// 初始化语言包
this.initializeLocales()
}
private initializeLocales() {
// 遍历所有语言文件
Object.entries(localeFiles).forEach(([path, content]) => {
// 解析路径获取语言代码和命名空间
// 例如: ./locales/zh-CN/common.json
const matches = path.match(/\.\/locales\/([^/]+)\/([^.]+)\.json/)
if (matches) {
const [, locale, namespace] = matches
// 初始化语言对象
if (!this.messages[locale]) {
this.messages[locale] = {}
}
try {
// 赋值
const messages = content
// 按命名空间存储消息
this.messages[locale][namespace] = messages
} catch (error) {
console.error(`解析语言文件失败 ${path}:`, error)
}
}
})
}
// 获取特定语言的消息
getMessages(locale: string): LocaleMessages {
return this.messages[locale] || {}
}
// 获取支持的语言列表
getSupportedLocales(): string[] {
return Object.keys(this.messages)
}
}
场景三:插件系统
// plugins/manager.ts
// 定义插件接口
interface Plugin {
name: string;
install: (app: any) => void;
priority?: number;
}
// 导入所有插件
const pluginModules = import.meta.glob<{ default: Plugin }>('./*/index.ts')
export class PluginManager {
// 存储已加载的插件
private loadedPlugins: Plugin[] = []
// 加载所有插件
async loadPlugins(): Promise<void> {
// 存储加载Promise
const loadPromises: Promise<void>[] = []
// 遍历所有插件模块
for (const path in pluginModules) {
const loadPromise = (async () => {
try {
// 加载插件模块
const module = await pluginModules[path]()
const plugin = module.default
// 验证插件格式
if (!plugin.name || !plugin.install) {
throw new Error(`插件格式无效: ${path}`)
}
// 添加到已加载插件列表
this.loadedPlugins.push(plugin)
} catch (error) {
console.error(`加载插件失败 ${path}:`, error)
}
})()
loadPromises.push(loadPromise)
}
// 等待所有插件加载完成
await Promise.all(loadPromises)
// 按优先级排序
this.loadedPlugins.sort((a, b) =>
(b.priority || 0) - (a.priority || 0)
)
}
// 安装所有插件
async installPlugins(app: any): Promise<void> {
// 确保插件已加载
if (this.loadedPlugins.length === 0) {
await this.loadPlugins()
}
// 安装每个插件
for (const plugin of this.loadedPlugins) {
try {
await plugin.install(app)
console.log(`插件 ${plugin.name} 安装成功`)
} catch (error) {
console.error(`插件 ${plugin.name} 安装失败:`, error)
}
}
}
}
4. 使用注意事项
- 路径规范:
// 正确用法
const modules = import.meta.glob('./components/*.vue')
// 错误用法 - 不支持动态路径
// import.meta.glob 的参数都必须以字面量传入。
// 你不可以在其中使用变量或表达式。
const path = './components'
const modules = import.meta.glob(`${path}/*.vue`) // ❌
- 性能考虑:
// 异步加载 - 代码分割,按需加载
const modules = import.meta.glob('./modules/*.ts')
// 同步加载 - 所有模块打包在一起
const modules = import.meta.glob('./modules/*.ts', { eager: true })
- 类型支持:
// 定义模块类型
interface ModuleType {
name: string;
setup: () => void;
}
// 使用泛型指定类型
const modules = import.meta.glob<ModuleType>('./modules/*.ts', {
eager: true
})
这些示例展示了 import.meta.glob
在不同场景下的应用,每个示例都包含了详细的注释和错误处理,可以作为实际项目中的参考。