1、Vue Router 是什么?
Vue Router 是 Vue.js 的官方路由管理器,用于构建单页面应用(SPA - Single Page Application)。它让 Vue.js 应用能够实现:
- 多页面效果(实际上只有一个 HTML 页面)
- URL 地址变化时,页面内容动态更新
- 浏览器的前进/后退功能
- 页面导航和跳转
2、为什么需要 Vue Router?
传统网站 vs 单页面应用
传统多页面网站:
用户点击链接 → 浏览器向服务器请求新页面 → 服务器返回完整HTML → 页面完全刷新
Vue 单页面应用(使用 Vue Router):
用户点击链接 → Vue Router 拦截 → 动态加载对应组件 → 局部更新页面内容
没有页面刷新,体验更流畅
3、安装与基本配置
1、安装
html
npm install vue-router --save-dev
如果在一个模块化工程中使用,必须通过Vue.use()显示声明路由功能
html
import Vue from'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter);
2、基本配置 src目录下创建文件夹router,专门存放路由,router下新建index.js
javascript
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
// 1. 导入自定义的路由组件
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import User from '../views/User.vue'
import NotFound from '../views/NotFound.vue'
// 2. 定义路由
const routes = [
{
//路由路径
path: '/',
//路由名称
name: 'Home',
//跳转到的组件
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
{
path: '/user/:id',
name: 'User',
component: User,
props: true // 将路由参数作为 props 传递
},
{
path: '/:pathMatch(.*)*', // 404 页面
name: 'NotFound',
component: NotFound
}
]
// 3. 创建路由实例
const router = createRouter({
// 使用 HTML5 历史模式
history: createWebHistory(),
// 使用 hash 模式
// history: createWebHashHistory(),
routes
})
export default router
在main.js文件中配置路由
javascript
// main.js
import { createApp } from 'vue'
import App from './App.vue'
// 导入上边创建的路由配置目录
import router from './router'
const app = createApp(App)
//配置路由
app.use(router)
app.mount('#app')
4、在App.vue中路由的使用
javascript
<template>
<div id="app">
<!-- 导航栏 -->
<nav>
<router-link to="/">首页</router-link> |
<router-link to="/about">备注</router-link> |
<router-link :to="{ name: 'User', params: { id: 123 }}">用户信息</router-link>
</nav>
<!-- 路由出口,展示路由组件的内容 -->
<router-view v-slot="{ Component }">
<!-- 路由过渡效果 -->
<transition name="fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
<!-- 命名视图 -->
<router-view name="sidebar" />
</div>
</template>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
5、编程式导航
javascript
<script setup>
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
// 导航到不同页面
const goHome = () => {
router.push('/')
// 或
// router.push({ path: '/' })
// 或
// router.push({ name: 'Home' })
}
const goAbout = () => {
router.push('/about')
}
const goUser = (id) => {
router.push({
name: 'User',
params: { id },
query: { tab: 'profile' } // 添加查询参数
})
}
// 替换当前路由(不记录历史)
const replaceRoute = () => {
router.replace('/about')
}
// 前进/后退
const goBack = () => {
router.go(-1) // 后退一步
}
const goForward = () => {
router.go(1) // 前进一步
}
// 获取路由参数
const userId = route.params.id
const tab = route.query.tab
// 监听路由变化
import { watch } from 'vue'
watch(
() => route.params.id,
(newId) => {
console.log('用户ID变化:', newId)
}
)
</script>
6、嵌套路由
路由配置文件
javascript
// router/index.js
const routes = [
{
path: '/user/:id',
component: UserLayout,
children: [
{
path: '',
name: 'UserProfile',
component: UserProfile
},
{
path: 'posts',
name: 'UserPosts',
component: UserPosts
},
{
path: 'settings',
name: 'UserSettings',
component: UserSettings
}
]
}
]
组件页面
javascript
<!-- User.vue -->
<template>
<div>
<h2>用户页面</h2>
<nav>
<router-link :to="`/user/${$route.params.id}`">查看资料</router-link>
<router-link :to="`/user/${$route.params.id}/posts`">检阅文章</router-link>
<router-link :to="`/user/${$route.params.id}/settings`">系统设置</router-link>
</nav>
<router-view />
</div>
</template>
7、路由守卫
1、全局守卫
javascript
// router/index.js
router.beforeEach((to, from) => {
// 返回 false 取消导航
// 返回路径字符串重定向
// 返回 undefined 或 true 继续导航
console.log('从', from.path, '到', to.path)
// 检查是否需要登录
if (to.meta.requiresAuth && !isAuthenticated()) {
return {
name: 'Login',
query: { redirect: to.fullPath }
}
}
})
router.afterEach((to, from) => {
// 导航完成后执行
document.title = to.meta.title || '默认标题'
})
2、路由独享守卫
javascript
{
path: '/admin',
component: Admin,
meta: { requiresAuth: true },
beforeEnter: (to, from) => {
// 仅对该路由生效
if (!isAdmin()) {
return { name: 'Home' }
}
}
}
3、组件内守卫
javascript
<script setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
// 离开守卫
onBeforeRouteLeave((to, from) => {
if (hasUnsavedChanges) {
return confirm('有未保存的更改,确定离开吗?')
}
})
// 路由更新守卫
onBeforeRouteUpdate((to, from) => {
// 重新获取数据
fetchData(to.params.id)
})
</script>
8、路由元信息和懒加载
javascript
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue'), // 懒加载
meta: {
title: '首页',
requiresAuth: false
}
},
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('../views/Dashboard.vue'),
meta: {
title: '数据',
requiresAuth: true,
roles: ['admin', 'editor'] // 权限控制
}
}
]
// 路由元信息的使用
router.beforeEach((to, from) => {
if (to.meta.requiresAuth) {
const user = getUserInfo()
if (!user) {
return { name: 'Login' }
}
if (to.meta.roles && !to.meta.roles.includes(user.role)) {
return { name: 'Forbidden' }
}
}
})
9、滚动行为
javascript
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
// 返回锚点位置
if (to.hash) {
return {
el: to.hash,
behavior: 'smooth'
}
}
// 返回之前的位置
if (savedPosition) {
return savedPosition
}
// 默认滚动到顶部
return { top: 0 }
}
})
10、动态路由
javascript
// 添加路由
router.addRoute({
path: '/new-route',
component: () => import('../views/NewRoute.vue')
})
// 删除路由
const removeRoute = router.addRoute({ /* ... */ })
removeRoute() // 删除添加的路由
// 获取所有路由
const allRoutes = router.getRoutes()
// 动态路由权限控制
function setupRoutes(userRole) {
const routes = [
{ path: '/', component: Home }
]
if (userRole === 'admin') {
routes.push({
path: '/admin',
component: () => import('../views/Admin.vue')
})
}
// 重置路由
router.removeRoute('admin')
routes.forEach(route => {
router.addRoute(route)
})
}
11、补充
1、常用工具函数
javascript
<script setup>
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
// 判断当前路由
const isActive = (path) => {
return route.path === path
}
// 获取完整路径
const fullPath = route.fullPath
// 获取查询参数
const queryParams = route.query
// 路由匹配
const matchedRoutes = route.matched
</script>
2、路由跳转时传递数据
javascript
// 通过 query
router.push({
path: '/user',
query: { id: 123456, name: '张三' }
})
// 通过 params(需要命名路由)
router.push({
name: 'User',
params: { id: 123456, name: '张三' }
})
// 在组件中接收
const route = useRoute()
const id = route.params.id
const name = route.query.name