溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解Vue路由自動注入實踐

發(fā)布時間:2020-09-18 09:57:53 來源:腳本之家 閱讀:214 作者:Qymh 欄目:web開發(fā)

什么是路由自動注入

路由自動注入概念學習自nuxt,我們不需要在 router.js 中每次手動輸入代碼引入模塊而是自動根據(jù) 文件目錄格式 生成 router.js

我們把這個功能獨立成一個 webpack 插件,并對相關功能進行了完善,而且實現(xiàn)了 vue-router 的所有核心功能

更詳細使用指南和文檔可以查看我們的 github倉庫

舉一個簡單的列子,比如你的目錄長這樣

src
├── views
│ ├── Login
│ │ └── Index.vue
│ └── User
│  ├── Account
│  │ └── Index.vue
│  ├── Home
│  │ └── Index.vue
│  └── Index.vue

規(guī)則很簡單,如果目錄的一層是 Index.vue ,則目錄名便是當前的路由名字,如果是子文件夾則是第二層路由,之后自動生成的 router.js 會長成這樣

{
 component: () =>
 import('@/views/Login/Index.vue'),
 name: 'login',
 path: '/login'
},
{
 component: () =>
 import('@/views/User/Index.vue'),
 name: 'user',
 path: '/user'
},
{
 component: () =>
 import('@/views/User/Account/Index.vue'),
 name: 'user-account',
 path: '/user/account'
},
{
 component: () =>
 import('@/views/User/Home/Index.vue'),
 name: 'user-home',
 path: '/user/home'
}

這里值得一提的是其實生成的 router.js 是沒有必要加入到版本控制當中的,因為不論在開發(fā)( development )還是生產( production )第一次構建項目都會自動生成,比如你項目用到了 giteslint ,那么應該把它放在 .gitignore.eslintignore

為什么使用路由自動注入

方便

不用每次去引用模塊,只用創(chuàng)建文件夾, router.js 會自動生成

統(tǒng)一路由命名

詳解Vue路由自動注入實踐

如果有完整的 code review 這個問題是不會存在的,但我們稍微做了一點簡便,只要 code review 文件夾的命名就好了,最終生成的路由path會以駝峰命名,生成的name會以駝峰命名并且以連字符 - 連接不同層級的路由

統(tǒng)一路由層級

詳解Vue路由自動注入實踐

如圖片中的列子,我們無法從文件的命名去判斷路由到底在幾級,而且經常寫的時候,明明是2級或3級路由卻和1級路由在一層路由下,這是很不規(guī)范而且與邏輯不符的

對比一下使用自動注入劃分層級后的路由

src/views
├── Index.vue
├── NotFound.vue
├── Withdraw
 <!-- 第一級 -->
│ ├── Index.vue
│ └── Result
│  ├── Description
   <!-- 第三級 -->
│  │ └── Index.vue
  <!-- 第二級 -->
│  └── Index.vue
└── WithdrawHistory
 <!-- 第一級 -->
 └── Index.vue

可以從目錄結構看出路由的層級

我們再來看看生成的路由,不同層級的路由名字通過連字符 - 連接,層級很清晰

{
 component: () => import('@/views/Withdraw/Index.vue'),
 name: 'withdraw',
 path: '/withdraw'
},
{
 component: () => import('@/views/Withdraw/Result/Index.vue'),
 name: 'withdraw-result',
 path: '/withdraw/result'
},
{
 component: () => import('@/views/Withdraw/Result/Description/Index.vue'),
 name: 'withdraw-result-description',
 path: '/withdraw/result/description'
},
{
 component: () => import('@/views/WithdrawHistory/Index.vue'),
 name: 'withdrawHistory',
 path: '/withdrawHistory'
},

為什么選擇 vue-router-invoke-webpack-plugin

完善的單元測試

詳解Vue路由自動注入實踐

types支持

詳解Vue路由自動注入實踐

vue-router-invoke-webpack-plugin 中獨特的路由劃分思維

當我們的頁面過多的時候,比如項目有60多個甚至70多個單頁面,文件不可能會放在一個目錄下,一般這種時候,我們會按 功能 將相似功能的路由放在一個目錄下,我們之前也是這么做的,其實這么做也是沒啥問題的,但在路由自動注入下,我們提出了另外一種思路按路由 層級 劃分

什么是層級劃分呢,簡單的一句話就是根據(jù)頁面所在的相對url地址進行劃分,舉個列子,我們的首頁如下

詳解Vue路由自動注入實踐

首頁的路由為 / ,我們把首頁當作根路由,那么可以進入的一級路由分別為 提現(xiàn) 提現(xiàn)記錄 分成數(shù)據(jù) 等,點擊提現(xiàn)后,我們進入了提現(xiàn)路由 /withdraw

詳解Vue路由自動注入實踐

進入提現(xiàn)頁面后,會有兩處可點擊,這兩處便是二級頁面,放在一級頁面的子文件夾中,按剛才的說法,路由目錄(截取部分)便是這樣

src/views
├── Bank
 <!-- 銀行卡管理 -->
│ └── Index.vue
├── DivideData
 <!-- 分成數(shù)據(jù) -->
│ └── Index.vue
<!- 首頁 --->
├── Index.vue
<!-- 404路由 -->
├── NotFound.vue
├── Withdraw
│ ├── BankDetails
  <!-- 提現(xiàn)中查看銀行卡信息 -->
│ │ └── Index.vue
│ ├── Description
  <!-- 提現(xiàn)說明 -->
│ │ └── Index.vue
 <!-- 提現(xiàn)頁面 -->
│ └── Index.vue
└── WithdrawHistory
  <!--提現(xiàn)記錄 -->
 └── Index.vue

其實一般這么分下來,相似功能的是會在一個文件夾下面的,也實現(xiàn)了按功能分路由的思路,而且這種層級劃分是一目了然的,很容易可以看出路由的從屬關系

但有時候也會遇到一個麻煩,就是有些頁面可能出現(xiàn)在當前層級下面,也可能出現(xiàn)在另外一個層級下面,按功能分的時候也有這種,就是功能可能存在于兩個功能點之間,這種情況其實可以考慮下在哪個層級的權重重一點或者從用戶的點擊習慣考慮,哪個位置進去會多一點就放在哪個層級下面

vue-router-invoke-webpack-plugin 中獨特的文件結構

也許大家會有疑問,為啥非要寫成 Index.vue 并多加一層文件夾封裝,直接命名 vue 文件不好嗎,用過 nuxt 的同學可能也會感覺到這一點的區(qū)別,這也是我們在 nuxt 的基礎上增加的一個 feature ,為了更友好的封裝一個單頁面

舉個列子,如果你的項目沒有引用ui庫,很多業(yè)務組件需要自己寫,除了常用的組件會放在目錄最外面的 components 文件,其余的對應一個單頁面的業(yè)務組件你會放在哪里呢,這就是我們預留的位置,比如一個目錄結構如下

src/views
├── Audit
│ ├── Index.vue
│ ├── components
│ │ └── AuditItem.vue
│ └── images
│  └── AuditIntro.png

Audit 是我們的審批頁面,其中用到了一個只有當前頁面所用的 AuditItem.vue 組件,也引用了一個只有當前頁面所用到的圖片 AuditIntro.png ,獨特的文件結構就是為了這種需求而生的,當前頁面的組件圖片放在一個文件夾中會更清晰,但值得一提的是,你也需要在插件中設置 ignore 去忽略掉不被我們解析的目錄,比如這樣

plugins: [
 new VueRouterInvokeWebpackPlugin({
 dir: 'src/views',
 alias: '@/views',
 language: 'javascript',
 ignore: ['images', 'components', 'template.vue']
 })
];

那么 images components template.vue 會被忽略不解析

聊一聊路由權限控制

關于前端控制路由權限,前段時間看到過一個文章,感覺實現(xiàn)思路稍微復雜了點,其實有一個比較簡單的思路,就是后端給定當前用戶沒有權限的路由,然后前端在 beforeEach 鉤子中去匹配,如果匹配到沒有權限則直接跳404或者沒有權限的頁面就行了,如果用 vue-router-invoke-webpack-plugin 寫會這么寫

apis.getForbiddenRoute

export default {
 // 請求當前沒有權限的路由列表
 async getForbiddenRoute() {
 return ['/single/user'];
 }
};
plugins: [
 new VueRouterInvokePlugin({
  // 觀察的目錄
  dir: 'demos/src',
  // 觀察目錄的別名
  alias: '@/src',
  // 當前語言
  language: 'javascript',
  // 生成router.js的位置
  routerDir: 'demos',
  // 忽略文件夾
  ignore: ['images', 'template.vue', 'components', 'notfound.vue'],
  // 404路由地址
  notFound: '@/src/NotFound.vue',
  // 引用的模塊
  modules: [
  {
   name: 'apis',
   package: '@/apis'
  }
  ],
  // 同scrollBehavior
  scrollBehavior: (to, from, savedPosition) => {
  if (savedPosition) {
   return savedPosition;
  } else {
   return { x: 0, y: 0 };
  }
  },
  <!-- 主要是這段代碼 -->
  /* eslint-disable */
  beforeEach: async (to, from, next) => {
  // 通過綁定在靜態(tài)屬性上的_cachedForbiddenRoute判斷是否請求過接口
  if (!Vue._cachedForbiddenRoute) {
   Vue._cachedForbiddenRoute = [];
   await apis.getForbiddenRoute().then(res => {
   Vue._cachedForbiddenRoute = res;
   });
  }
  // 當當前頁面的地址存在于禁止訪問的列表中,則直接跳轉到404頁面
  if (Vue._cachedForbiddenRoute.includes(to.path)) {
   next({
   name: 'notFound'
   });
  } else {
   next();
  }
  }
 }),
]

但話說回來,任何實現(xiàn)思路,前端獲取的接口數(shù)據(jù)想篡改還是能繞過去的,所以還是得后端再防一層

項目實現(xiàn)思路

項目實現(xiàn)不太復雜,但要照顧到的地方很多

  • 基本路由
  • 動態(tài)路由
  • 多層嵌套路由
  • 多層嵌套動態(tài)路由
  • meta替代品
  • 文件不符合規(guī)則的友好處理
  • 命名轉換統(tǒng)一
  • node中原生fs模塊十分不友好

要考慮的小細節(jié)還挺多的,特別是當路由過于復雜的情況

但node的 fs 的坑點是我沒有想到的,特別是在跨平臺上,所以我們舍棄了使用原生的 fs 模塊,用 chokidarfs-extra 替代了 fs 的部分功能

前段時間也在學習 vue 的ast語法樹,所以學習了下思路去嘗試構建一棵ast,不過方法還是有區(qū)別的,vue構建語法樹是通過正則拆分了 元素開始標簽 元素屬性 元素字符 元素結束標簽 等然后拼接而成的,拼接的過程特別復雜,這個項目會簡單很多,直接通過文件讀取遞歸遍歷目錄就可以生成一棵 ast

詳解Vue路由自動注入實踐

然后通過語法樹去構建字符串的 router.js ,構建的過程還比較麻煩,最后將構建好的字符串寫入文件就大功告成了

項目還需要完善的地方

單元測試

現(xiàn)在的單元測試覆蓋率已經100%了,但我覺得仍然有比較多稍微復雜的情況沒有寫到,之后會不僅看單元測試覆蓋率,而是按想到需要測試得功能點去補充完整

測試環(huán)境

項目接入的是 circleci ,沒法在 windows 下測試,平常用的開發(fā)環(huán)境也是 mac ,所以測試環(huán)境方面之后還要去研究研究其他可以支持windows的ci工具,并對不同node版本進行測試

其實現(xiàn)在在 windows 下也有一個bug,但我發(fā)現(xiàn) nuxt 也有這個bug,所以感覺可能這不是一個bug或許是一個feature,之后也會去提一個 issue 去請教一下,也不知道是不是我電腦的問題,簡單說就是 fs.watch 去監(jiān)聽文件目錄的時候(但這里其實用的是 chokidar ,不過都一樣)當去改變之前已有的文件目錄的名字是改不了的, windows 下會提示你什么當前文件被引用了,需要結束掉進程這個文件名才能被修改

更友好的支持

項目目前支持的是node版本> 8.15.1,僅支持 webpack4 ,之后會支持 webpack3 和即將到來的 webpack5

更多的功能

除了剛才提到的一個簡單路由的列子和設置忽略項,我們還支持了 vue-router 的其他核心功能,包括 動態(tài)路由 嵌套路由 全局路由守衛(wèi) meta替代品 等其他功能,相關功能點都寫在了我們開源倉庫的文檔中,詳細的用法和注意事項,可以訪問我們的 github倉庫 ,如果覺得項目還不錯的話,可以給我們點一顆小星星,當然如果你在使用中發(fā)現(xiàn)了和預期不太一樣的情況或者bug可以隨時給我們提 issue

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI