神奇!這款 Vue 後臺框架居然不用手動配置路由

胡尐睿丶發表於2022-02-28

前言

做 Vue 開發脫離不了路由,尤其是中大型專案,頁面多且雜,在配置路由的時候總是會變得逐漸暴躁,因為費時,並且又沒有什麼太多技術含量,總覺得是在浪費時間。

另外如果接手了別人的專案,當業務有變更,或者測試反饋有 bug 。通常需要先要根據頁面 URL 去找到對應配置的路由,然後對照 component 引數對應的 .vue 檔案,操作繁瑣,效率也不高。

那有沒有一種辦法可以根據 .vue 檔案自動生成路由,並且路由的 path 就是檔案所在的資料夾路徑,這樣即節省了路由配置的時間,也提高了根據 URL 定位頁面檔案的效率。

經過我的一番查詢,還真找到了,就是下面這兩個外掛:

使用

安裝

從這兩款外掛的名字可以看出,這倆是 vite 的外掛,並且僅支援 Vue3 ,那我就搬出我的 Fantastic-template 專案模版拿來測試了。

首先先安裝依賴。因為模版裡自帶了 vue-router ,所以不需要再安裝。

pnpm add vite-plugin-pages vite-plugin-vue-layouts -D

安裝好依賴後,需要在 vite.config.js 裡進行配置,由於這兩個外掛作用不同,我們一個個來介紹如何使用。

vite-plugin-pages

這個是本次介紹的核心,它能夠將檔案系統生成對應的路由,從而省去手動配置路由的時間。

首先在 vite.config.js 增加以下配置:

import Pages from 'vite-plugin-pages'

export default {
    plugins: [
        Pages({
            dirs: 'src/views',  // 需要生成路由的檔案目錄
            exclude: ['**/components/*.vue']  // 排除在外的目錄,即不將所有 components 目錄下的 .vue 檔案生成路由
        })
    ]
}

目前只需要配置這 2 個引數就夠了,其它還有更多引數可以去 vite-plugin-pages 專案頁瞭解。

接著在頁面中引入就可以使用了。

import { createRouter } from 'vue-router'
import routes from '~pages'

const router = createRouter({
    // ...
    routes
})

沒錯,就是這麼簡單,當然也有一些高階用法。比如通過 params 傳參的路由,要怎麼配置呢?

在 vite-plugin-pages 裡提供了一種專用的寫法,就是 [ ] 。例如 src/views/example/[id].vue 這個檔案,最終生成的路由 path 就是 /example/:id

針對 404 頁面,我們可以在建立個這樣的檔案 src/views/[...all].vue ,它生成的路由就是 /:all(.*)*

除此之外,我們還可以在 .vue 檔案中增加 <route></route> 程式碼塊,這裡面預設接收 json5 格式的路由配置。需要注意的是,如果在 <route></route> 裡配置了 pathname ,將會覆蓋自動生成的 pathname

<route>
{
    path: '/xxx/yyy',
    name: 'zzz',
    meta: {
        title: 'test page'
    }
}
</route>

<template>
	<div>
        This is a test page.
    </div>
</template>

這時候似乎還缺點什麼,對的,那就是巢狀路由。通過 vite-plugin-pages 自動生成的路由,都是一級路由。而實際專案開發中,我們會使用巢狀路由的特性,搭配 <router-view></router-view> 元件實現一些佈局效果。

這時候就要介紹下面這款外掛了

vite-plugin-vue-layouts

首先在 vite.config.js 修改下配置:

import Pages from 'vite-plugin-pages'
import Layouts from 'vite-plugin-vue-layouts'

export default {
    plugins: [
        Pages({
            dirs: 'src/views',  // 需要生成路由的檔案目錄
            exclude: ['**/components/*.vue']  // 排除在外的目錄,即所有 components 目錄下的 .vue 檔案都不會生成路由
        }),
        Layouts({
            layoutsDirs: 'src/layout',  // 佈局檔案存放目錄
            defaultLayout: 'index'  // 預設佈局,對應 src/layout/index.vue
        })
    ]
}

更多配置引數請檢視 vite-plugin-vue-layouts 專案頁。

也還是一樣,配置好後,就可以直接使用了。

import { createRouter } from 'vue-router'
import { setupLayouts } from 'virtual:generated-layouts'
import generatedRoutes from 'virtual:generated-pages'

const routes = setupLayouts(generatedRoutes)

const router = createRouter({
    // ...
    routes
})

這個外掛只做一件事,就是把通過 vite-plugin-pages 生成的一級路由處理成巢狀路由,大概就是這樣:

// 處理前
{
    path: '/login',
    component: () => import('/src/views/login.vue'),
    name: 'login'
}

// 處理後
{
    path: '/login',
    component: () => import('/src/layout/index.vue'),
    children: [
        {
            path: '',
            component: () => import('/src/views/login.vue'),
            name: 'login'
        }
    ]
}

如果你有多種佈局,可以在 <route><route> 裡進行設定:

<route>
{
    meta: {
        layout: 'other'
    }
}
</route>

甚至還可以做一些魔改,比如專案中有的路由是需要用到佈局頁面的,有的則不需要,那我們可以將不需要的頁面設定為 layout: false

<route>
{
    meta: {
        layout: false
    }
}
</route>

同時在路由檔案處使用下面這段程式碼:

import { createRouter } from 'vue-router'
import { setupLayouts } from 'virtual:generated-layouts'
import generatedRoutes from 'virtual:generated-pages'

let routes = []
generatedRoutes.forEach(v => {
    routes.push(v?.meta?.layout != false ? setupLayouts([v])[0] : v)
})

const router = createRouter({
    // ...
    routes
})

總結

通過下面這張圖配合總結吧:

檔案系統                           路由地址                          路由 name

views
├─ example
│    ├─ components
│    │    └─ List
│    │         └─ index.vue
│    ├─ params
│    │    └─ [id].vue              /example/params/:id              example-params
│    ├─ axios.vue                  /example/axios                   example-axios
│    ├─ cookie.vue                 /example/cookie                  example-cookie
│    └─ svgicon.vue                /example/svgicon                 example-svgicon
├─ [...all].vue                    /:all(.*)*                       all
├─ index.vue                       /                                index
└─ login.vue                       /login                           login
  • 使用路由引數需通過 [ ] 將引數名包裹,並設為檔名
  • 資料夾不會生成路由,例如 example 資料夾並沒有生成 /example 路由
  • 路由 name 會根據檔案的目錄結構自動生成,並用 - 連線,可確保 name 的唯一性
  • 所有 components 目錄均不會生成路由

點題

這麼好用的特性,我也是第一時間整合進了我開發的 Fantastic-admin 後臺框架中,如果你感興趣,可以點我詳細瞭解如何使用。

相關文章