Vue+TypeScript+ElementUI 实战 (二)vue-router 路由模块化

375 阅读2分钟

在使用vue开发中,前期常常会将所有的路由写在一个文件中。但是当项目过大的时候,会面临路由文件过程,难以维护的问题。

大的项目中一般都会分为很多模块,每个模块都是独立的,而且每个模块最好也有自己独立的路由文件,便于项目后期的拓展和维护

当路由文件越来越多得时候,逐个去引入就特别麻烦而且多人合作代码容易冲突,那么我们可以通过webpack的 require.context() 函数,自动导入vue-router模块

在封装之前我们先来了解一下 require.context() 函数

1、require.context()

一个webpack的api,通过执行 require.context 函数获取一个特定的上下文 , 主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块

1.1 参数

require.context函数接受三个参数

  • directory {String} - 读取文件的路径

  • useSubdirectories {Boolean} - 是否遍历文件的子目录

  • regExp {RegExp} -匹配文件的正则

1.2 语法

require.context(directory, useSubdirectories = false, regExp = /^.//);

1.3 示例

借用webpakc官网的例子

require.context('./test', false, /.test.ts$/)

上面的代码遍历当前目录下的test文件夹的所有.test.js结尾的文件, 不遍历子目录

大概用图片来表示的话就是这样子的

在这里插入图片描述

在index.js中调用 require.context('./test', false, /.test.js$/); 会得到test文件下3个文件的执行环境

值得注意的是

require.context函数执行后返回的是一个函数,并且这个函数有3个属性

  • resolve {Function} -接受一个参数request,request为test文件夹下面匹配文件的相对路径,返回这个匹配文件相对于整个工程的相对路径

  • keys {Function} - 返回匹配成功模块的名字组成的数组

  • id {String} - 执行环境的id,返回的是一个字符串,主要用在module.hot.accept,应该是热加载?

这三个都是作为函数的属性(注意是作为函数的属性,函数也是对象,有对应的属性)

我们可以通过打印看下返回值:

const modulesFiles = require.context('./test', false, /.test.ts$/)
console.dir(modulesFiles)
console.log('resolve: ' + modulesFiles.resolve(modulesFiles.keys()[0]))
console.log('keys: ' + modulesFiles.keys())
console.log('id: ' + modulesFiles.id)

在这里插入图片描述

talk is cheap ,show me the code

2、 vue-router 模块化

2.1 分割路由文件

router                           // 路由文件夹
  |__index.ts                    // 路由组织器:用来初始化路由等等
  |__modules                     // 业务逻辑模块:所以的业务逻辑模块
        |__a.ts                  // 业务模块a
        |__b.ts                  // 业务模块b
        |__c.ts                  // 业务模块c

这边我们先尝试把 about 和 home 页面分割出来,如下: 在这里插入图片描述

2.2 modules文件夹

modules文件夹中存放着所有的业务模块,业务模块内容根据具体业务自行编写。 本文代码仅为示例。

about.ts

export default [{
  path: '/about',
  name: 'About',
  component: () => import('@/views/About.vue'),
  meta: {
    outMenu: true
  }
}]

home.ts

export default [{
  path: '/',
  name: 'Home',
  component: () => import('@/views/Home.vue'),
  meta: {
    outMenu: true
  }
}]

2.3 index.ts 自动化导入模块

import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'

Vue.use(VueRouter)

const modulesRoutes: Array<RouteConfig> = []

// 自动加载路由配置
const modulesFiles = require.context('./modules', false, /.+\.ts$/)
modulesFiles.keys().forEach((modulePath: string) => {
  /**
   *  modulesFiles(modulePath)是Module对象,有个属性default,通过modulesFiles(modulePath).default便可获取到对应模块所导出的内容。
   */
  modulesFiles(modulePath).default && modulesRoutes.push(...modulesFiles(modulePath).default)
})

const routes: Array<RouteConfig> = [
  ...modulesRoutes,
   // 也可在此添加公用的页面
  {
    path: '*',
    component: () => import('@/views/404.vue'),
    meta: {
      notLogin: true
    }
  }
]

const router = new VueRouter({
  routes
})

export default router