require.context在vue中的实际应用--自动化引入文件,解放你的双手

4,477 阅读1分钟

require.context详解

require.context

可以给这个函数传入三个参数:一个要搜索的目录,一个标记表示是否还搜索其子目录, 以及一个匹配文件的正则表达式

示例

require.context('./test', false, /\.test\.js$/);
// (创建出)一个 context,其中文件来自 test 目录,request 以 `.test.js` 结尾。

require.context会返回一个webpack式的上下文环境,其实质是一个function,此导出函数有三个属性:resolve, keys, id。

  • resolve 是一个函数,它返回 request 被解析后得到的模块 id。
  • keys 也是一个函数,它返回一个数组,由所有可能被此 context module 处理的请求组成。
  • id:上下文模块的id

优化vuex中的modules写法

store中的文件结构

原来的引入方式

这种写法每次添加一个module都要自己手动引入,module命名改动也比较麻烦,并且大型项目中module比较多了之后代码就会显得比较臃肿

import Vue from 'vue';
import Vuex from 'vuex';
import one from './one';
import two from './two';
import three from './three';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    one,
    two,
    three
  }
});

改进后

这样操作之后,就能实现自动化加入module,无论有多少,或者module有改动的话,这部分文件都不用再次改动了

import Vue from 'vue';
import Vuex from 'vuex';

const modules = {};
// 只匹配子文件夹的index.js  ./one/index.js
const files = require.context('./', true, /^\.\/(\w*\/)+index\.js$/);

files.keys().forEach(file => {
  const moduleName = file.replace(/(^\.\/)|(\/index\.js$)/g, '');
  modules[moduleName] = files(file).default || files(file);
});

Vue.use(Vuex);

export default new Vuex.Store({
  modules
});

优化组件引入

原来的写法

import HelloWorld from "@/components/HelloWorld.vue";
import Second from "@/components/Second.vue";
import Third from "@/components/Third.vue";

export default {
  name: "Home",
  components: {
    HelloWorld,
    Second,
    Third
  }
};

改进后

const files = require.context("@/components", true, /\.vue$/);
let components = {};
files.keys().forEach(file => {
  let componentName = files(file).default.name;
  components[componentName] = files(file).default;
});
export default {
  name: "About",
  components
};

优化route

同样的,路由引入也可以进行类似的改造,实现智能化引入路由

目录结构

代码部分

import Vue from 'vue'
import Router from 'vue-router'

const files = require.context("./views", true, /^.\/(\w+\/)?\w+.vue$/, 'lazy');
const routerItem = (name, modules = {}) => {
  let [dot, parent, child] = name.split('/');
  parent = parent && parent.replace(/.vue$/, '');
  child = child && child.replace(/.vue$/, '');

  if(!modules[parent]) {
    const finalName = child ? `./${parent}/index.vue` : `./${parent}.vue`;
    modules[parent] = {
      path: '/' + parent,
      name: parent,
      component: () => Vue.component(parent, files(finalName))
    };
  }
  if(child && child !== 'index') {
    const fullName = parent + child.charAt().toUpperCase() + child.slice(1);
    (modules[parent].children || (modules[parent].children = [])).push({
      path: "/" + fullName,
      name: fullName,
      component: () => Vue.component(fullName, files(name))
    });
  }
};

const modules = ( (modules) => {
  files.keys().map(file => {
    routerItem(file, modules);
  });
  return Object.keys(modules).map(item => modules[item]);
})({});

Vue.use(Router);

export default new Router({
  mode: "history",
  routes: [
    ...modules,
  ]
});

require.context真的非常香,逼格十足,还不赶快在你的vue项目中使用起来吗?