淺入深出Vue:自動化路由
在軟體開發的過程中,"自動化"這個詞出現的頻率是比較高的。自動化測試,自動化資料對映以及各式的程式碼生成器。這些詞語的背後,也說明了在軟體開發的過程中,對於那些重複、千篇一律的事情。人們總是想讓它自己完成,來解放我們的雙手。
“懶惰”是進步的動力
為什麼要自動化路由
路由自動化在於解決以下的問題:
每次新建頁面時的重複操作:在路由檔案中新增對應的路由物件。
路由與程式碼耦合:路由依賴於路由物件的硬編碼,當某一路由發生變動時,勢必需要修改對應的路由物件。當路由層級、路徑發生改變時,甚至可能面臨的是整個路由物件陣列的重寫。
路由之間進行跳轉時的硬編碼。
目的很簡單,在開發過程中,開發者僅需要做兩件事即可:
為這個路由命名
在對應的目錄下建立
.vue
檔案
開發過程中只需要做這兩步,無需再去關心路由物件如何編寫。
甚至可以忽略第一步,對於小型專案而言。
自動化路由規則
這些規則一部分是給開發者看,另一部分是給程式看的:
路由目錄需要指定
路由目錄下,每一層(一個資料夾即為一層)必須要有一個
Layout.vue
檔案,用來渲染子路由。路由目錄下的元件路徑即為其對應的路由,比如指定了
src/views
資料夾,裡面的src/views/admin/users
對應的路由即是:localhost/admin/users
。路由目錄下不區分大小寫,統一轉換成小寫處理。
以上便是我們制定的自動化路由規則。
定義
先提取出三個概念:
自動化路由的提供者,它就是對外開放的介面,開發者只需要使用它就可以。
檢視,指的是一個檢視元件的相關資訊,比如路徑、名稱等等。
路由,指的是解析檢視之後對應的路由物件,用於生成vue-router
的路由物件。
開始開發
由於程式碼過長,這裡將程式碼上傳至 Github
, 有興趣的童鞋可以去看看。
這裡只描述一下整體流程以及關鍵部分的程式碼思路。
先通過
require.context
獲取到指定目錄下的所有.vue
檔案。通過字首以及排序操作,將其還原成目錄結構。
通過還原的目錄結構,進行解析。
將解析後的結構轉換成路由物件。
其中最關鍵的地方便是通過require.context
還原成樹形結構之後就可以對應樹形結構進行路由物件的生成了。
首先將檔案列表進行排序,根據檔案的深度進行排序,深度淺的在前,深的在後。
_getViews(dir) {
let views = [];
let keys = dir.keys();
for (let index in keys) {
let path = keys[index];
let component = dir(path);
views.push(View.create(path, component.default || component))
}
views = views.sort((x, y) => { return x.Deep > y.Deep ? 1 : -1; });
return views;
}
根據排序後的列表對目錄結構進行還原:
/**
* 解析views,生成對應的目錄結構
* @private
*/
_generateDirectory() {
for (let index in this._views) {
let view = this._views[index];
this._directory.addView(view);
}
}
addView
方法:
addView(view) {
if(this.isCurrentDirectoryView(view)) {
this._views.push(view);
} else if(this._isInSubDirectory(view)) {
this._addInSubDirectory(view);
} else {
let newSubDirectory = this._createSubDirectory(view);
newSubDirectory.addView(view);
this._subDirectory.push(newSubDirectory);
}
}
對於目錄還原時有三種可能:
這個檔案就是當前目錄下的檔案
這個檔案是當前目錄下已有子目錄的檔案
這個檔案是當前目錄下子目錄的檔案,且為首次出現
將目錄還原後,就可以根據目錄生成對應的路由物件。並且在生成時可以做一些定製化的需求,比如開篇提出來的需求:
如果當前檔案是
Layout.vue
,即預設為當前路由的根路由如果當前檔案是
Index.vue
, 即預設為當前層的空路由(根路由入口直接渲染)
使用方法,將 router.js
中的路由物件替換成自動生成的即可:
import Vue from 'vue'
import Router from 'vue-router'
import Generator from './routerGenerator/generator';
Vue.use(Router);
let generator = new Generator(require.context('./views', true, /\.vue$/));
export default new Router({
routes: [generator.generate()]
})
目錄結構如下:
效果如下:
github地址:https://github.com/WhileKing/ea-router
npm地址:https://www.npmjs.com/package/ea-router
npm包安裝使用:
npm i ea-router