Vue Router 4.x
Vue Router 简介
Vue Router 是 Vue.js 官方的路由管理器。它与 Vue.js 核心深度集成,让构建单页应用(SPA)变得轻松简单。Vue Router 4.x 是专为 Vue 3 设计的路由管理器,它完全支持 Vue 3 的 Composition API,并且在很多地方都做了优化和改进。
主要功能包括:
- 嵌套的路由/视图表
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于 Vue.js 过渡系统的视图过渡效果
- 细粒度的导航控制
- 带有自动激活的 CSS class 的链接
- HTML5 历史模式或 hash 模式
- 自定义的滚动行为
- URL 的正确编码
下载安装
直接下载 / CDN
<script src="https://unpkg.com/vue@3"></script>
<script src="https://unpkg.com/vue-router@4"></script>
安装
npm install vue-router@4
pnpm add vue-router@4
yarn add vue-router@4
在 Vue 3 中使用
在 Vue 3 项目中使用 Vue Router 需要注意版本兼容性:
- Vue 2.x 需要使用 Vue Router 3.x 版本
- Vue 3.x 需要使用 Vue Router 4.x 版本
使用方法
基本用法
import { createMemoryHistory, createRouter } from 'vue-router'
import HomeView from './HomeView.vue'
const routes = [
{ path: '/', component: HomeView },
// 懒加载
{ path: '/about', component: () => import('./AboutView.vue') },
]
const router = createRouter({
history: createMemoryHistory(),
routes,
})
export default router
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
动态路由匹配
正则:
const routes = [
// 动态路径参数以冒号开头
{ path: '/:orderId' },
// /:orderId -> 仅匹配数字
{ path: '/:orderId(\\d+)' },
// 匹配所有路径,通常用于 404 页面
{ path: '/:pathMatch(.*)*' },
]
可重复参数:
const routes = [
// /:chapters -> 匹配 /one, /one/two, /one/two/three, 等
{ path: '/:chapters+' },
// /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等
{ path: '/:chapters*' },
]
// 给定 { path: '/:chapters*', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 产生 /
router.resolve({ name: 'chapters', params: { chapters: ['a', 'b'] } }).href
// 产生 /a/b
// 给定 { path: '/:chapters+', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 抛出错误,因为 `chapters` 为空
// 仅匹配数字
const routes = [
// 匹配 /1, /1/2, 等
{ path: '/:chapters(\\d+)+' },
// 匹配 /, /1, /1/2, 等
{ path: '/:chapters(\\d+)*' },
]
const router = createRouter({
history: createWebHistory(),
routes: [
// 将匹配 /users/posva 而非:
// - /users/posva/ 当 strict: true
// - /Users/posva 当 sensitive: true
{ path: '/users/:id', sensitive: true },
// 将匹配 /users, /Users, 以及 /users/42 而非 /users/ 或 /users/42/
{ path: '/users/:id?' },
],
strict: true, // applies to all routes
})
可选参数:
const routes = [
// 匹配 /users 和 /users/posva
{ path: '/users/:userId?' },
// 匹配 /users 和 /users/42
{ path: '/users/:userId(\\d+)?' },
]
嵌套路由
const routes = [
{
path: '/user/:id',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: 'posts',
component: UserPosts,
},
],
},
]
<template>
<router-view />
</template>
<template>
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view />
</div>
</template>
命名路由
const routes = [
{
path: '/user/:username',
name: 'profile',
component: User
}
]
使用 <router-link>
:
<router-link :to="{ name: 'profile', params: { username: 'erina' } }">
User profile
</router-link>
编程式导航:
router.push({ name: 'user', params: { username: 'erina' } })
编程式导航
// 字符串路径
router.push('/users/eduardo')
// 带有路径的对象
router.push({ path: '/users/eduardo' })
// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })
// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })
// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })
// `params` 不能与 `path` 一起使用
router.push({ path: '/user', params: { username } }) // -> /user
// 替换当前路由,参数与 router.push 一致
router.replace({ path: '/home' })
// 向前移动一条记录,与 router.forward() 相同
router.go(1)
// 返回一条记录,与 router.back() 相同
router.go(-1)
// 前进 3 条记录
router.go(3)
// 如果没有那么多记录,静默失败
router.go(-100)
router.go(100)
命名视图
const routes = [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
对应的模板:
<router-view></router-view>
<router-view name="a"></router-view>
<router-view name="b"></router-view>
路由模式
Vue Router 4 提供了多种路由模式,通过 history 配置项进行设置:
Hash 模式
Hash 模式使用 URL 的 hash 来模拟一个完整的 URL。当 URL 改变时,页面不会重新加载。
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
routes: [...]
})
在 hash 模式下,URL 会带有 #
符号,例如:http://yoursite.com/#/user/id
。
History 模式
History 模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面,URL 更加美观。
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [...]
})
在 history 模式下,URL 看起来像正常的 URL,例如:http://yoursite.com/user/id
。
使用 history 模式时需要注意,需要服务器配置支持。因为这是一个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://yoursite.com/user/id
就会返回 404。
关于服务器配置的详细示例,请查看 Vue Router 服务器配置示例。
需要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面。
Memory 模式
Memory 模式不依赖于浏览器的 URL,而是使用一个内部数组来存储路由历史记录。主要用于 Node.js 环境中,例如服务端渲染。
import { createRouter, createMemoryHistory } from 'vue-router'
const router = createRouter({
history: createMemoryHistory(),
routes: [...]
})
Composition API 支持
Vue Router 4 完全支持 Vue 3 的 Composition API,提供了两个主要的组合式函数:
useRouter
用于访问路由实例:
import { useRouter } from 'vue-router'
export default {
setup() {
const router = useRouter()
function navigate() {
router.push('/home')
}
return { navigate }
}
}
useRoute
用于访问当前路由对象:
import { useRoute } from 'vue-router'
export default {
setup() {
const route = useRoute()
// 访问路由参数
const userId = route.params.id
return { userId }
}
}
主要变化
Vue Router 4 相比于 Vue Router 3 有以下主要变化:
1. 安装方式变化
// Vue Router 3
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
routes
})
// Vue Router 4
import { createRouter } from 'vue-router'
const router = createRouter({
routes
})
2. 模式配置变化
// Vue Router 3
const router = new VueRouter({
mode: 'history', // 或 'hash'
routes
})
// Vue Router 4
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(), // 或 createWebHashHistory()
routes
})
3. 对 Composition API 的支持
Vue Router 4 完全支持 Vue 3 的 Composition API,提供了 useRouter 和 useRoute 组合式函数。
4. 更好的 TypeScript 支持
Vue Router 4 用 TypeScript 重写,提供了更好的类型推断和检查。
5. 动态路由的改进
Vue Router 4 对动态路由进行了优化,提供了更好的 API 来添加和删除路由。
实践应用
路由守卫
用于权限验证和页面访问控制。
// 全局前置守卫
router.beforeEach((to, from) => {
// 验证用户是否已登录
if (to.meta.requiresAuth && !isAuthenticated()) {
// 返回 false 以取消导航
return {
path: '/login',
query: { redirect: to.fullPath }
}
}
})
// 组件内守卫
export default {
async beforeRouteUpdate(to, from) {
// 对路由变化作出响应
this.userData = await fetchUser(to.params.id)
}
}
路由懒加载
优化应用性能。
const routes = [
{
path: '/foo',
component: () => import('./Foo.vue')
}
]
滚动行为
控制页面滚动位置
const router = createRouter({
history: createWebHistory(),
routes: [...],
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
}
})
结合 Transition 和 KeepAlive
这样可以实现动画过渡和缓存的效果。
<script setup>
const cacheList = ref([ /* ... */ ])
const transitionName = ref('')
// 获取缓存的 key
const getKey = (route) => {
// 根据的项目需要,可自定义实现
return route.fullPath
}
</script>
<template>
<RouterView v-slot="{ Component, route }">
<Transition :name="transitionName" appear mode="out-in">
<KeepAlive :include="cacheList">
<component :is="Component" :key="getKey(route)" />
</KeepAlive>
</Transition>
</RouterView>
</template>