【知识整理】批量导入require.context和import.meta.glob

415 阅读2分钟

项目中经常会使用到批量导入,这会帮助减少相似代码的编写

并且它还很多使用场景:

  • 在组件内引入多个子组件
  • 在main.js中批量引入注册全局组件
  • 批量导入路由文件批量注册
  • 引入vuex的module

一、require.context


(1)如果项目是基于webpack构建的,就可以使用require.context来实现批量导入

此函数传入三个参数:

  • 搜索的目录
  • 表示是否搜索其子目录
  • 匹配文件的正则表达式
require.context('./test', false, /\.js$/);
// 批量导入test文件夹下的js文件,不考虑其子目录

(2)require.context导出一个函数,此函数有一个属性:keys

  • keys 也是一个函数,它返回一个数组

(3)示例

3.1 示例一:

新建一个test文件夹,里面有三个文件

a.js 里有console.log('a')

b.js 里有console.log('b')

c.js 里有console.log('c')

平常引入方式:

import './test/a'
import './test/b'
import './test/c'

批量引入方式:

function importAll(r: any) {
  r.keys().forEach(r)
}
importAll(require.context('./test', false, /\.js$/))

3.2 示例二: vue3项目批量注册全局组件

const app = createApp(App)
const module = require.context('./components', false, /\.vue$/)
module.keys().forEach((fileName) => {
  // 组件实例
  const comInstance = module(fileName).default || module(fileName)
  // 组件实例name属性作为组件名称
  const comName = comInstance.name
  // 全局组件注册
  app.component(comName, comInstance)
})

注:

module(fileName).default 返回的是Es6规范暴露的内容(如:export default)

module(fileName) 返回的是CommonJs规范暴露的内容(如:module.exports)

二、import.meta.glob


(1)如果项目是基于vite构建的,就可以使用import.meta.glob来实现批量导入

此函数传入二个参数

  • 搜索的目录
  • 配置对象

{ eager: true }置是否直接引入所有的模块
{ import: 'default' }配置是否加载默认导出。

(2)示例

2.1 示例一:

新建一个test文件夹,里面有三个文件

a.js 里有console.log('a')

b.js 里有console.log('b')

c.js 里有console.log('c')

const modules = import.meta.glob('./test/*.js');

以上将会被转译为下面的样子:并不能直接导入

// vite 生成的代码 
const modules = { 
  './test/a.js': () => import('./test/a.js'),
  './test/b.js': () => import('./test/b.js'),
  './test/c.js': () => import('./test/c.js'),
}

当然,可以遍历 module 对象的 key 值来访问相应的模块

for (const path in modules) { 
  modules[path]().then((mod) => { 
    console.log(path, mod) 
  })
}

增加 { eager: true } 配置,在上面编译的基础上,增加import直接导入

const modules = import.meta.glob('./test/*.js', {eager: true});

2.2 示例二:vue3项目批量注册全局组件

import { defineAsyncComponent, createApp } from 'vue'

const app = createApp(App)
// 获取components路径任意文件夹下的 index.vue 文件
const modules = import.meta.glob('./components/*/index.vue')
// 遍历获取到的组件模块
for (const [key, value] of Object.entries(modules)) {
  // 组件名称
  const componentName =  key.split('/')[2]
  // 通过 defineAsyncComponent 异步导入指定路径下的组件
  app.component(componentName, defineAsyncComponent(value))
}