淺入深出Vue:自動化路由

  • 2019 年 10 月 3 日
  • 筆記

在軟體開發的過程中,"自動化"這個詞出現的頻率是比較高的。自動化測試自動化數據映射以及各式的程式碼生成器。這些詞語的背後,也說明了在軟體開發的過程中,對於那些重複千篇一律的事情。人們總是想讓它自己完成,來解放我們的雙手。

「懶惰」是進步的動力

為什麼要自動化路由

路由自動化在於解決以下的問題:

  • 每次新建頁面時的重複操作:在路由文件中添加對應的路由對象。

  • 路由與程式碼耦合:路由依賴於路由對象的硬編碼,當某一路由發生變動時,勢必需要修改對應的路由對象。當路由層級、路徑發生改變時,甚至可能面臨的是整個路由對象數組的重寫。

  • 路由之間進行跳轉時的硬編碼。

目的很簡單,在開發過程中,開發者僅需要做兩件事即可:

  1. 為這個路由命名

  2. 在對應的目錄下創建 .vue 文件

開發過程中只需要做這兩步,無需再去關心路由對象如何編寫。

甚至可以忽略第一步,對於小型項目而言。

自動化路由規則

這些規則一部分是給開發者看,另一部分是給程式看的:

  1. 路由目錄需要指定

  2. 路由目錄下,每一層(一個文件夾即為一層)必須要有一個 Layout.vue文件,用來渲染子路由。

  3. 路由目錄下的組件路徑即為其對應的路由,比如指定了 src/views文件夾,裡面的 src/views/admin/users 對應的路由即是: localhost/admin/users

  4. 路由目錄下不區分大小寫,統一轉換成小寫處理。

以上便是我們制定的自動化路由規則。

定義

先提取出三個概念:

自動化路由的提供者,它就是對外開放的介面,開發者只需要使用它就可以。

視圖,指的是一個視圖組件的相關資訊,比如路徑、名稱等等。

路由,指的是解析視圖之後對應的路由對象,用於生成vue-router的路由對象。

開始開發

由於程式碼過長,這裡將程式碼上傳至 Github, 有興趣的童鞋可以去看看。
這裡只描述一下整體流程以及關鍵部分的程式碼思路。

  1. 先通過 require.context 獲取到指定目錄下的所有 .vue 文件。

  2. 通過前綴以及排序操作,將其還原成目錄結構。

  3. 通過還原的目錄結構,進行解析。

  4. 將解析後的結構轉換成路由對象。

其中最關鍵的地方便是通過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