前端动态导入(import.meta.glob) 的实用场景和详细示例

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 在实际项目中的高级应用。每个示例都包含了:

  • 文件组织结构的建议
  • 命名规范的处理
  • 类型安全的考虑
  • 实际业务场景的适配

通过这些模式,可以构建出更加模块化、可维护的项目结构。

相关推荐
用户479492835691521 分钟前
mcp是怎么和大模型进行交互的,有哪些交互方式
前端·人工智能
凤年徐31 分钟前
解锁网页魔法:零基础HTML通关秘籍
前端·javascript·css·前端框架·html·web
PineappleCoder33 分钟前
防抖 vs 节流:高频事件的 “性能优化双雄” 怎么用?
前端·javascript·面试
小old弟34 分钟前
🤔面试官问你:什么是高阶函数?举例说明用到过的...
前端
是你的小橘呀35 分钟前
从小区广场舞群聊,看懂前端 er 必懂的发布订阅模式
前端
margicCode35 分钟前
0-1搭建项目基本配置(eslint+prettier)到release-it发布
前端
ZzMemory38 分钟前
CSS 命名太乱?BEM 规范帮你一键搞定,代码清爽到飞起!
前端·css·面试
大道小路38 分钟前
Vue3 组件数据传输小全
前端·javascript·vue.js
初辰ge38 分钟前
pCameraH5 v2.0:轻量级 H5 相机插件全新升级,支持拍照、录像与自定义水印
前端·javascript
Mr_Swilder39 分钟前
Chapter 8 Light and Color 光与颜色
前端