1. 程式人生 > >vue 自動化路由實現

vue 自動化路由實現

1.需求描述

在寫vue的專案中,一般情況下我們每新增一個新頁面都得新增一個新路由。為此我們在專案中會專門的一個資料夾來管理路由,如下圖所示

 

 

 那麼有沒有一種方案,能夠實現我們在資料夾中新建了一個vue檔案,就自動幫我們新增路由。特別在我們的一個ERP後臺專案中,我們幾乎都是一個資料夾下有很多子檔案,子檔案中一般包含index.vue, detail.vue, edit.vue,分別對應的事列表頁,詳情頁和編輯頁。

 

 

 上圖是我們的檔案目錄,views資料夾中存放的是所有的頁面,goodsPlanning是一級目錄,onNewComplete和thirdGoods是二級目錄,二級目錄中存放的是具體的頁面,indexComponents中存放的是index.vue的檔案,editComponents也是同樣的道理。index.vue對應的路由是/goodsPlanning/onNewComplete, edit.vue對應的路由是/goodsPlanning/onNewComplete/edit,detail.vue也是同樣的道理。所以我們的資料夾和路由是完全能夠對應上的,只要知道路由,就能很快的找到對應的檔案。那麼有沒有辦法能夠讀取我們二級目錄下的所有檔案,然後根據檔名來生成路由呢?答案是有的

2. require.context介紹

官方文件require.context

簡單說就是:有了require.context,我們可以得到指定資料夾下的所有檔案

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

require.context有三個引數:

  • directory:說明需要檢索的目錄
  • useSubdirectories:是否檢索子目錄
  • regExp: 匹配檔案的正則表示式

require.context()的返回值,有一個keys方法,返回的是個陣列

let routers = require.context('VIEWS', true).keys()
console.log(routers)

 

 

 

 

 

 

 通過上面的程式碼,我們打印出了所有的views資料夾下的所有檔案和資料夾,我們只要寫好正則就能找到我們所需要的檔案

3.直接上程式碼

import Layout from 'VIEWS/layout/index'

/**
 * 正則 首先匹配./ ,然後一級目錄,不包含components的二級目錄,以.vue結尾的三級目錄
 */
let routers = require.context('VIEWS', true, /\.\/[a-z]+\/(?!components)[a-z]+\/[a-z]+\.vue$/i).keys()
let indexRouterMap = {}  // 用來儲存以index.vue結尾的檔案,因為index.vue是列表檔案,需要加入layout(我們的選單),需要keepAlive,需要做許可權判斷
let detailRouterArr = [] // 用來儲存以非index.vue結尾的vue檔案,此類目前不需要layout
routers.forEach(item => {
  const paths = item.match(/[a-zA-Z]+/g)  //paths中儲存了一個目錄,二級目錄,檔名
  const routerChild = {  //定義路由物件
    path: paths[1],     
    name: `${paths[0]}${_.upperFirst(paths[1])}`,   //upperFirst,lodash 首字母大寫方法
    component(resolve) {
      require([`../../views${item.slice(1)}`], resolve)
    },
  }
  if (/index\.vue$/.test(item)) {  //判斷是否以index。vue結尾
    if (indexRouterMap[paths[0]]) {   //判斷一級路由是否存在,存在push二級路由,不存在則新建
      indexRouterMap[paths[0]].children.push(routerChild)
    } else {
      indexRouterMap[paths[0]] = {
        path: '/' + paths[0],
        component: Layout,
        children: [routerChild]
      }
    }
  } else {     //不以index.vue結尾的,直接新增到路由中
    detailRouterArr.push({
      path: item.slice(1, -4),   //渠道最前面的 . 和最後的.vue
      name: `${paths[0]}${_.upperFirst(paths[1])}${_.upperFirst(paths[2])}`,
      component(resolve) {
        require([`../../views${item.slice(1)}`], resolve)
      },
      meta: {
        noCache: true,   //不keepAlive
        noVerify: true   //不做許可權驗證
      }
    })
  }
})

export default [
  ...Object.values(indexRouterMap),
  ...detailRouterArr,
  /**
   * dashboard單獨處理下
   */
  {
    path: '',
    component: Layout,
    redirect: 'dashboard',
    children: [
      {
        path: 'dashboard',
        component: () => import('VIEWS/dashboard/index'),
        name: 'dashboard',
        meta: { title: '首頁', noCache: true, noVerify: true }
      }
    ]
  },
]

簡簡單單的幾十行程式碼就實現了所有的路由功能,再也不用一行一行的寫路由檔案了。可能你的檔案管理方式和我的不一樣,但是隻要稍微改改正則就行了。

 

4. 注意

  1. 不能用import引入路由,因為用import引入不支援變數
  2. 不能用別名,找了半天問題,才知道用變數時也不能用別名,所以我用的都是相對路徑

5.好處

  • 不用在新增路由了,這個就不說了,明眼人都看得出來
  • 知道了路由,一個能找到對應的檔案,以前我們團隊就出現過,亂寫path的情況
  • 更好的控制驗證和keepAlive