邓嘉倪 發表於 2025-5-16 17:17:00

记录---前端动态导入(import.meta.glob)

<h1 data-id="heading-0">🧑‍💻 写在开头</h1>
<p>点赞 + 收藏 === 学会🤣🤣🤣</p>
<p>以下详细介绍&nbsp;<code>import.meta.glob</code>&nbsp;的使用:</p>
<h3 data-id="heading-0">1. 参数详解</h3>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">import.meta.glob(
pattern,          // 匹配模式:字符串或字符串数组
{
    eager?: boolean, // 是否同步导入
    import?: string | string[], // 指定导入的内容
    query?: string|Record&lt;string, string | number | boolean&gt; // 查询参数
}
)</pre>
</div>
<blockquote>
<p>pattern 通配符详解</p>
</blockquote>
<h3 data-id="heading-1">2. 基础示例(带详细注释)</h3>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// 1. 基本异步导入
const modules = import.meta.glob('./modules/*.ts')

async function loadModules() {
// 遍历所有匹配的模块
for (const path in modules) {
    // 等待模块加载完成
    const module = await modules()
    // 输出模块路径和内容
    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' // 排除特定目录
])</pre>
</div>
<h3 data-id="heading-2">3. 实际使用场景</h3>
<h4 data-id="heading-3">场景一:动态组件加载系统</h4>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// components/loader.ts

// 定义组件模块的类型
interface ComponentModule {
default: any; // Vue 组件
meta?: {
    name: string;
    version: string;
}
}

// 导入所有组件
const componentModules = import.meta.glob&lt;ComponentModule&gt;('./*/index.vue')

export class ComponentLoader {
// 存储已加载的组件
private loadedComponents: Map&lt;string, any&gt; = new Map()

// 加载组件
async loadComponent(name: string): Promise&lt;any&gt; {
    // 构建组件路径
    const componentPath = `./${name}/index.vue`
   
    // 检查组件是否存在
    if (!componentModules) {
      throw new Error(`组件 ${name} 不存在`)
    }
   
    // 检查是否已加载
    if (this.loadedComponents.has(name)) {
      return this.loadedComponents.get(name)
    }
   
    try {
      // 加载组件
      const module = await componentModules()
      // 存储组件
      this.loadedComponents.set(name, module.default)
      return module.default
    } catch (error) {
      throw new Error(`加载组件 ${name} 失败: ${error.message}`)
    }
}
}</pre>
</div>
<h4 data-id="heading-4">场景二:多语言文件管理系统</h4>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// i18n/loader.ts

// 定义语言包类型
interface LocaleMessages {
: any;
}

// 导入所有语言文件
const localeFiles = import.meta.glob('./locales/**/*.json', {
eager: true // 同步导入
})

export class I18nLoader {
// 存储语言包
private messages: Record&lt;string, LocaleMessages&gt; = {}

constructor() {
    // 初始化语言包
    this.initializeLocales()
}

private initializeLocales() {
    // 遍历所有语言文件
    Object.entries(localeFiles).forEach(() =&gt; {
      // 解析路径获取语言代码和命名空间
      // 例如: ./locales/zh-CN/common.json
      const matches = path.match(/\.\/locales\/([^/]+)\/([^.]+)\.json/)
      if (matches) {
      const [, locale, namespace] = matches
      
      // 初始化语言对象
      if (!this.messages) {
          this.messages = {}
      }
      
      try {
          // 赋值
          const messages = content
          // 按命名空间存储消息
          this.messages = messages
      } catch (error) {
          console.error(`解析语言文件失败 ${path}:`, error)
      }
      }
    })
}

// 获取特定语言的消息
getMessages(locale: string): LocaleMessages {
    return this.messages || {}
}

// 获取支持的语言列表
getSupportedLocales(): string[] {
    return Object.keys(this.messages)
}
}</pre>
</div>
<h4 data-id="heading-5">场景三:插件系统</h4>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// plugins/manager.ts

// 定义插件接口
interface Plugin {
name: string;
install: (app: any) =&gt; void;
priority?: number;
}

// 导入所有插件
const pluginModules = import.meta.glob&lt;{ default: Plugin }&gt;('./*/index.ts')

export class PluginManager {
// 存储已加载的插件
private loadedPlugins: Plugin[] = []

// 加载所有插件
async loadPlugins(): Promise&lt;void&gt; {
    // 存储加载Promise
    const loadPromises: Promise&lt;void&gt;[] = []
   
    // 遍历所有插件模块
    for (const path in pluginModules) {
      const loadPromise = (async () =&gt; {
      try {
          // 加载插件模块
          const module = await pluginModules()
          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) =&gt;
      (b.priority || 0) - (a.priority || 0)
    )
}

// 安装所有插件
async installPlugins(app: any): Promise&lt;void&gt; {
    // 确保插件已加载
    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)
      }
    }
}
}</pre>
</div>
<h3 data-id="heading-6">4. 使用注意事项</h3>
<ol>
<li>路径规范:</li>
</ol>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// 正确用法
const modules = import.meta.glob('./components/*.vue')

// 错误用法 - 不支持动态路径
// import.meta.glob 的参数都必须以字面量传入。
// 你不可以在其中使用变量或表达式。
const path = './components'
const modules = import.meta.glob(`${path}/*.vue`) // ❌</pre>
</div>
<ol start="2">
<li>性能考虑:</li>
</ol>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// 异步加载 - 代码分割,按需加载
const modules = import.meta.glob('./modules/*.ts')

// 同步加载 - 所有模块打包在一起
const modules = import.meta.glob('./modules/*.ts', { eager: true })</pre>
</div>
<ol start="3">
<li>类型支持:</li>
</ol>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// 定义模块类型
interface ModuleType {
name: string;
setup: () =&gt; void;
}

// 使用泛型指定类型
const modules = import.meta.glob&lt;ModuleType&gt;('./modules/*.ts', {
eager: true
})</pre>
</div>
<p>这些示例展示了&nbsp;<code>import.meta.glob</code>&nbsp;在不同场景下的应用,每个示例都包含了详细的注释和错误处理,可以作为实际项目中的参考。</p>
<div>
<h2>本文转载于:https://juejin.cn/post/7485263262507925531</h2>
</div>
<h3 id="tid-D8HBxE">如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。</h3>
<p><img src="https://img2024.cnblogs.com/blog/2149129/202501/2149129-20250122165814748-630765389.png" alt="" loading="lazy"></p><br><br>
来源:https://www.cnblogs.com/smileZAZ/p/18880321
頁: [1]
查看完整版本: 记录---前端动态导入(import.meta.glob)