在軟件開發的過程當中,"自動化"這個詞出現的頻率是比較高的。自動化測試,自動化數據映射以及各式的代碼生成器。這些詞語的背後,也說明了在軟件開發的過程當中,對於那些重複、千篇一概的事情。人們老是想讓它本身完成,來解放咱們的雙手。javascript
「懶惰」是進步的動力vue
路由自動化在於解決如下的問題:java
每次新建頁面時的重複操做:在路由文件中添加對應的路由對象。git
路由與代碼耦合:路由依賴於路由對象的硬編碼,當某一路由發生變更時,勢必須要修改對應的路由對象。當路由層級、路徑發生改變時,甚至可能面臨的是整個路由對象數組的重寫。github
路由之間進行跳轉時的硬編碼。vue-router
目的很簡單,在開發過程當中,開發者僅須要作兩件事便可:npm
爲這個路由命名數組
在對應的目錄下建立 .vue
文件測試
開發過程當中只須要作這兩步,無需再去關心路由對象如何編寫。ui
甚至能夠忽略第一步,對於小型項目而言。
這些規則一部分是給開發者看,另外一部分是給程序看的:
路由目錄須要指定
路由目錄下,每一層(一個文件夾即爲一層)必須要有一個 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