跳至主要内容

【套件】自動生成 vue-router

環境為 vite + vue3

使用過Nuxt開發後, 就覺得 Nuxt的Automatic Routes 非常的方便,

但由於目前公司傾向使用Vue3開發, 並且Nuxt3也還在RC階段, 所以只能重回基本的 vue-router 懷抱.

不過經過一番搜尋後, 發現了這兩個套件 「 vite-plugin-vue-layoutsvite-plugin-pages 」, 他們能達成的效果跟 Nuxt的Automatic Routes 幾乎一樣的效果

接下來就來演示這神奇的套件

範例

安裝/設定

yarn add -D vite-plugin-pages
yarn add -D vite-plugin-vue-layouts
yarn add vue-router
  • vite.config.ts 引入套件
// vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

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

// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),

// https://github.com/hannoeru/vite-plugin-pages
Pages(),

// https://github.com/JohnCampionJr/vite-plugin-vue-layouts
Layouts(),
]
})
  • vue-router 引入套件設定
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import { setupLayouts } from 'virtual:generated-layouts'
import generatedRoutes from 'virtual:generated-pages'

const router = createRouter({
history: createWebHistory(),
routes: setupLayouts(generatedRoutes)
})

export default router
  • main.ts 引入 router
// main.ts
import { createApp } from 'vue'
import './index.css'
import App from './App.vue'

// router
import router from './router'

createApp(App)
.use(router)
.mount('#app')
  • tsconfig.json 引入套件規則
// tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"types": [
"vite-plugin-pages/client",
"vite-plugin-vue-layouts/client"
]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
  • App.vue 修改
// App.vue
<template>
<router-view />
</template>

資料夾結構

從官方說明知道, 可以定義多個資料夾名稱來定義Route

但這邊先fouce在pages資料夾

src/
├── features/
│ └── dashboard/
│ ├── code/
│ ├── components/
│ └── pages/
├── admin/
│ ├── code/
│ ├── components/
│ └── pages/
└── pages/

// vite.config.js
export default {
plugins: [
Pages({
dirs: [
{ dir: 'src/pages', baseRoute: '' },
{ dir: 'src/features/**/pages', baseRoute: 'features' },
{ dir: 'src/admin/pages', baseRoute: 'admin' },
],
}),
],
}

404頁面

使用此套件, 404頁面只需要開個資料夾名稱為 […all] 並開個 index.vue 即可

// src/pages/[...all]/index.vue

id頁面

而id頁面有兩種方式使用

1. src/pages/test-id-page/[id].vue
路由為 xxxx/test-id-page/:id

2. src/pages/items/index.vue
路由為 xxxx/items

2-1. src/pages/items/[id]/index.vue
路由為 xxxx/items/:id

2-2. src/pages/items/[id]/news.vue
路由為 xxxx/items/:id/news

router-view

當在特定頁面內想做router-view的切換時, 可以這樣做

// src/pages/router-view-test.vue
// 路由為 xxxx/router-view-test

<template>
<h1 class="text-2xl">router-view-test</h>
<div class="my-4">
<router-view></router-view>
</div>
</template>

建立資料夾及頁面

1. src/router-view-test/index.vue
路由為 xxxx/router-view-test

2. src/router-view-test/page2.vue
路由為 xxxx/router-view-test/page2

3. src/router-view-test/page3.vue
路由為 xxxx/router-view-test/page3

路由 layout

在最前面有安裝 layout 套件還沒使用到, 這個套件可以讓我們自訂每一個頁面的layout

預設 layout

預設為 src/layouts/default.vue, 設定好後即套用在所有頁面

// src/layouts/default.vue
<script setup lang="ts">
import Menu from "../components/menu.vue"
</script>

<template>
<main class="main">
<Menu />
<section class="w-full mx-auto max-w-[500px]">
<h1 class="text-4xl mb-10 mt-5">Layout 1</h1>
<router-view />
</section>
</main>
</template>

自訂 layout

假設自訂為 src/layouts/Layout2.vue, 並且想把他套用在404頁面

// src/layouts/Layout2.vue

<template>
<main class="main">
<section class="w-full mx-auto max-w-[500px]">
<h1 class="text-4xl mb-10 mt-5">Layout 2</h1>
<router-view />
</section>
</main>
</template>

可以直接在404頁面內設定 yaml 檔, 來決定該頁使用的 layout

// [...all].vue

<template>
<main class="flex flex-col items-center space-y-3">
<span class="text-2xl">
404
</span>
<router-link class="text-xl border p-1" to="/">回首頁</router-link>
</main>
</template>

<route lang="yaml">
meta:
layout: Layout2
</route>

yaml 內的 meta

meta 除了用來做 layout 的切換以外, 也能自訂值來做其他應用(ex. 路由驗證)

// member-only.vue

<template>
<h1 class="text-2xl">
會員頁
</h1>
</template>

<route lang="yaml">
meta:
layout: Layout2
auth: member-page
sss: router-is-good
</route>

該 meta 的可以從 router.beforeEach 內的 to.meta 看到剛剛打的物件, 如

localeDropdown

如此就能用這個值來達成會員頁以及訪客頁面的切換

Deploy 部署

https://vitejs.dev/guide/static-deploy.html#building-the-app

以git-page為例, 除了參考 vite 官方設定 base 位置以及sh檔案以外

需要額外到router檔案設定好位置, 才能正常執行,

若為 GCP 或 AWS 這類雲端空間則無需修改.

// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import { setupLayouts } from 'virtual:generated-layouts'
import generatedRoutes from 'virtual:generated-pages'

const router = createRouter({
history: createWebHistory('vue3-test-website'), // 修改這裏
routes: setupLayouts(generatedRoutes)
})

router.beforeEach(async (to, from, next) => {
console.log(to.meta)
next()
})

export default router

部署範例

https://jiangshuuu.github.io/vue3-test-website/

github repo

https://github.com/JiangShuuu/vue3-test-website/