Appearance
路由管理
Vue Router 基础
Vue Router是Vue.js的官方路由管理器,它与Vue.js核心深度集成,让构建单页应用变得轻而易举。
安装和基本设置
bash
npm install vue-router@4
基本路由配置
javascript
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import Profile from '../views/Profile.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
{
path: '/profile',
name: 'Profile',
component: Profile,
// 路由独享的守卫
beforeEnter: (to, from, next) => {
// 检查用户是否已登录
if (isUserLoggedIn()) {
next()
} else {
next('/login')
}
}
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
在应用中使用路由器
vue
<!-- App.vue -->
<script setup>
import { RouterLink, RouterView } from 'vue-router'
</script>
<template>
<div id="app">
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
<RouterLink to="/profile">Profile</RouterLink>
</nav>
<RouterView />
</div>
</template>
<style>
nav {
padding: 20px;
margin-bottom: 20px;
background-color: #f0f0f0;
}
nav a {
margin-right: 20px;
text-decoration: none;
color: #333;
}
nav a.router-link-active {
font-weight: bold;
color: #42b983;
}
</style>
</template>
动态路由匹配
Vue Router允许在路由路径中使用动态片段:
javascript
// router/index.js
const routes = [
{
path: '/user/:id',
name: 'User',
component: User
},
{
path: '/user/:id/post/:postId',
name: 'UserPost',
component: UserPost
},
// 可选参数
{
path: '/user/:id?/profile',
name: 'UserProfile',
component: UserProfile
}
]
vue
<!-- User.vue -->
<script setup>
import { useRoute } from 'vue-router'
import { computed } from 'vue'
const route = useRoute()
// 访问路由参数
const userId = computed(() => route.params.id)
// 当路由参数变化时,组件实例会被复用
// 需要监听参数变化
const route = useRoute()
// 在组合式API中监听参数变化
import { watch } from 'vue'
watch(
() => route.params.id,
(newId, oldId) => {
// 参数变化时的处理
fetchUserData(newId)
}
)
</script>
<template>
<div>
<h2>User ID: {{ userId }}</h2>
<!-- 组件内容 -->
</div>
</template>
</template>
嵌套路由
使用嵌套路由可以构建复杂的多层路由结构:
javascript
// router/index.js
const routes = [
{
path: '/user/:id',
component: User,
children: [
{
path: '', // 默认子路由
name: 'UserProfile',
component: UserProfile
},
{
path: 'posts',
name: 'UserPosts',
component: UserPosts
},
{
path: 'settings',
name: 'UserSettings',
component: UserSettings
}
]
}
]
vue
<!-- User.vue -->
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>
<template>
<div class="user-layout">
<h2>User: {{ route.params.id }}</h2>
<nav class="user-nav">
<RouterLink :to="`/user/${route.params.id}`">Profile</RouterLink>
<RouterLink :to="`/user/${route.params.id}/posts`">Posts</RouterLink>
<RouterLink :to="`/user/${route.params.id}/settings`">Settings</RouterLink>
</nav>
<RouterView />
</div>
</template>
## 编程式导航
除了使用[RouterLink](./components.md#router-link),还可以使用编程式导航:
```vue
<script setup>
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
// 字符串路径
function goToHome() {
router.push('/home')
}
// 对象形式
function goToUser(id) {
router.push({ path: `/user/${id}` })
}
// 命名路由
function goToUserProfile(id) {
router.push({
name: 'UserProfile',
params: { id: id }
})
}
// 带查询参数
function goToSearch(query) {
router.push({
path: '/search',
query: { q: query }
})
}
// 替换当前历史记录
function replaceTo(path) {
router.replace(path)
}
// 在历史记录中前进或后退
function goBack() {
router.go(-1)
}
function goForward() {
router.go(1)
}
function goSteps(steps) {
router.go(steps)
}
</script>
<template>
<div>
<button @click="goToHome">Go to Home</button>
<button @click="goToUser(123)">Go to User 123</button>
<button @click="goToUserProfile(123)">Go to User Profile</button>
<button @click="goBack">Go Back</button>
</div>
</template>
</template>
```
## 路由守卫
路由守卫允许我们在导航过程中执行一些逻辑:
### 全局前置守卫
```javascript
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({ ... })
// 全局前置守卫
router.beforeEach((to, from, next) => {
// 检查用户是否已登录
if (to.meta.requiresAuth && !isUserLoggedIn()) {
// 重定向到登录页
next('/login')
} else if (to.meta.requiresAuth && isUserLoggedIn()) {
// 已登录用户访问登录页则重定向到首页
if (to.path === '/login' && isUserLoggedIn()) {
next('/')
} else {
next()
}
} else {
next()
}
})
```
### 组件内守卫
```vue
<script setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
// 导航离开该组件的对应路由时调用
onBeforeRouteLeave((to, from, next) => {
const answer = window.confirm('Do you really want to leave? You have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
})
// 在当前路由改变,但是该组件被复用时调用
onBeforeRouteUpdate(async (to, from, next) => {
// 对路由变化做出响应...
if (from.params.id !== to.params.id) {
try {
// 获取新的用户数据
await fetchData(to.params.id)
next()
} catch (error) {
next(false)
}
} else {
next()
}
})
</script>
```
## 路由元信息
可以为路由添加元信息,用于路由守卫或组件逻辑:
```javascript
const routes = [
{
path: '/home',
component: Home,
meta: {
requiresAuth: false,
title: 'Home Page'
}
},
{
path: '/profile',
component: Profile,
meta: {
requiresAuth: true,
title: 'User Profile',
roles: ['user', 'admin']
}
},
{
path: '/admin',
component: Admin,
meta: {
requiresAuth: true,
requiresAdmin: true,
title: 'Admin Panel'
}
}
]
```
```vue
<!-- 在组件中访问元信息 -->
vue
<!-- 在组件中访问元信息 -->
<script setup>
import { useRoute } from 'vue-router'
import { onMounted } from 'vue'
const route = useRoute()
onMounted(() => {
// 设置页面标题
document.title = route.meta.title || 'Default Title'
})
</script>
路由管理是构建单页应用的核心,通过合理使用Vue Router的各种功能,可以创建出用户体验良好的导航系统。