自動化路由
- 前言
- 思路
- 使用node實作自動化router
- 使用webpack實作自動化router
前言
在中大型專案中,每次新建頁面都要去router檔案中添加對應的router物件,會覺得特別麻煩,而且多人開發還不好方便維護,甚至當router層級發生變化的時候,可能要重寫整個router物件陣列,因此我們需要一個自動化router
自動化router的最大好處:前端只需要專注寫代碼即可,無需關注路由的router檔案中的router.js
思路
在vue中,router.js必須的寫法
{
path: 'login',
name: 'login',
component: () => import('./views/Login')
},
因此我們只需要拿到import匯入的檔案路徑,然后設定它的path和name即可
重點是拿到檔案路徑,我們有兩種方式可以自動拿到檔案路徑,因此我們有兩種實作自動化路由的方法:
1、通過node 拿到檔案的路徑,
2、通過webpack的require.context() 方法拿到檔案的路徑
我們分別從兩種方式來實作自動化router
使用node實作自動化router
在node中,我們可以用fs和path兩個方法來獲取檔案路徑
var fs = require('fs')
const path = require('path')
我們在config下建立一個router.js檔案
利用遞回方法,輸出一個router.json,檔案名組成的陣列
// config.router.js
var fs = require('fs')
const path = require('path')
const config = require('./index')
const result = []
const readdir = (pagesPath, fileLevel = []) => {
const _dir = path.join(__dirname, pagesPath)
fs.readdirSync(_dir).forEach(fileName => {
const state = fs.lstatSync(_dir + '/' + fileName)
if (state.isDirectory()) { // 如果是目錄就往下找
readdir(pagesPath + '/' + fileName, fileLevel.concat(fileName))
} else if (/.vue/.test(fileName)) { // 如果是vue檔案
result.push(fileLevel.concat(fileName))
}
})
}
// 輸出檔案配置
readdir(config.router.pagesPath)
fs.writeFile(path.join(__dirname, '../src/router/router.json'), JSON.stringify(result), function (err) {
if (!err) {
console.log('===================')
console.log('router.json 配置完畢')
console.log('===================')
}
})
/*輸出結果如下
[["Index.vue"],["errer","Index.vue"],["home","Index.vue"],["mine","Edit.vue"],["mine","Index.vue"],["mine","editPSW","Index.vue"],["mine","info","Index.vue"]]
*/
對比輸出的json和我們檔案對比一下
[
["Index.vue"],
["errer","Index.vue"],
["home","Index.vue"],
["mine","Edit.vue"],
["mine","Index.vue"],
["mine","editPSW","Index.vue"],
["mine","info","Index.vue"]
]
|-- pages
|-- errer
|-- Index.vue
|-- home
|-- Index.vue
|-- mine
|-- editPSW
|-- Index.vue
|-- info
|-- Index.vue
|-- Edit.vue
|-- Index.vue
|-- Index.vue
通過對比,我們可以得到包含.vue檔案的名字和到pages下其父級檔案的所有名字
我們在main.js已經注冊router,因此我們在src的router檔案夾下創建一個initRouter.js,此js主要做如下的功能
- 自動化設定router的path
- 自動化設定router的name
- 自動化設定router的index
- 自動化設定router的defaultFileLevelList
- 自動化設定router的componentNames
- 自動化設定router的component
// src.router.initRouter.js
import importComponent from '../common/lib/importComponent' //自動化引入組件
export default (pageName = 'index') => {
const routerConfig = require('./router.json')
// 獲取頁面的路徑
const getPagePath = (connector = '/') => {
return pageName === 'index' ? '' : `${pageName}${connector}`
}
// 處理檔案路徑名稱
const filePath = (fileLevel) => {
let fl = JSON.parse(JSON.stringify(fileLevel))
return fl.join('/')
}
// 獲取組件名稱
const getImportComponentNames = (defaultFileLevel) => {
return `pages/${filePath(defaultFileLevel)}`
}
const initRoutes = (fileList) => {
const _list = []
fileList.forEach((fileLevel, index) => {
if (fileLevel[0] !== 'fusion' && fileLevel.length < 2) {
return
}
const defaultFileLevel = JSON.parse(JSON.stringify(fileLevel)) // 復制原始ITEM 防止被污染
const file = fileLevel.pop()
let fileName = file.split('.')[0]
fileName = fileName.substring(0, 1).toLowerCase() + fileName.substring(1)
const obj = {}
if (fileName.toLowerCase() !== 'index') {
fileLevel = fileLevel.concat(fileName)
} else {
obj.alias = `/${getPagePath()}${filePath(fileLevel)}/index`
}
const routerPath = `/${getPagePath()}${filePath(fileLevel)}`
const routerName = `${getPagePath('_')}${fileLevel.join('_')}`
_list.push({
...obj,
path: routerPath,
name: routerName,
index: index,
defaultFileLevelList: defaultFileLevel,
componentNames : getImportComponentNames(defaultFileLevel),
component: importComponent(getImportComponentNames(defaultFileLevel), (Module) => {
Module.default.name = routerName
})
})
})
return _list
}
return initRoutes(routerConfig)
}
我們在router檔案下的index.js,
此時把我們自動化生成的陣列放在new Router里即可就可以實作一個自動化路由的配置
// src.router.index.js
import getRouter from './initrouter'
import Vue from 'vue'
import Router from 'vue-router'
import resetRouterPush from '../common/lib/resetRouterPush'
resetRouterPush(Router)
Vue.use(Router)
const children = getRouter()
const router = new Router({
mode: 'history',
routes: [{
path: '/',
name: 'pages_Index',
component: () => import('@/pages/Index'),
redirect: '/home',
children
},
{//當跳轉路徑寫錯的時候,我們可以設定回到首頁、或者到自定義404頁面
path: '*',
redirect: '/errer'
}
]
})
export default router
最后我們在終端輸出
node config/router
終端顯示
此時在運行環境即可
-
擴展
- 我們也可以把node命令放到webpack里面,這樣子也可以使用npm run 來實作
-
注意:
- 每次檔案變更時候,必須運行node config/router
使用webpack實作自動化router
webpack提供了一個api:require.context()
寫法如下
require.context(directory,useSubdirectories,regExp)
- directory:表示檢索的目錄
- useSubdirectories:表示是否檢索子檔案夾
- regExp:匹配檔案的正則運算式,一般是檔案名
const routeFiles = require.context('@/pages', true, /\.vue/)
console.log(routeFiles)
通過使用require我們可以很容易的得到我們pages 下的全部vue檔案的路徑,因此他比node使用起來還要簡介,方便,
列印,我們可以看到,我們已經拿到相對路徑,并放在keys里面

我們只需在src/router/index.js檔案里
// router/index.js
import Vue from 'vue';
import vueRouter from 'vue-router'
Vue.use(vueRouter);
const getRouterName = (name)=>{
name = name.substring(1,name.length)
return name.split('/').join('_')
}
// // 查找 pages 下的全部vue檔案
const routeFiles = require.context('@/pages', true, /\.vue/)
let children = []
routeFiles.keys().forEach(item => {
let path = JSON.parse(JSON.stringify(item))
if(/\/Index.vue/.test(path)){//path去除index根檔案名
path = path.substring(0,path.length - 10)
}
if (path !== '.') { //因為父親是的路徑在/pages/Index下,因此我們不需要注冊改router
let info = path.split('.')
children.push({
path: info[1],
name: getRouterName(info[1]),
component: routeFiles(item).default
})
}
})
const router = new vueRouter({
mode: 'history',
routes: [{
path: '/',
name: 'pages_Index',
component: () => import('@/pages/Index'),
redirect: '/home',
children
},
{//當跳轉路徑寫錯的時候,我們可以設定回到首頁、或者到自定義404頁面
path: '*',
redirect: '/errer'
}
]
})
export default router;
- 擴展
- require.context()拿常常拿來寫自動化注冊全域組件
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/298967.html
標籤:其他
上一篇:js實作圖片的透明度運動
下一篇:js簡單抽獎
