官网
Vue3 中路由Vue Router 的使用实例详解
Vue 3 入门教程 8 - 路由管理 Vue Router
一. 安装命令
npm install vue-router@4
二. 创建路由配置文件
// src/router/index.js
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
import Home from '../views/home.vue'
import About from '../views/about.vue'
import Notfind from '../views/notfind.vue'
// createRouter 创建路由实例
// 配置 history 模式
// 1. history模式:createWebHistory 地址栏不带 #
// 2. hash模式: createWebHashHistory 地址栏带 #
// 注意: 如果将来你部署的域名路径是: https://www.baidu.com/XXX/home
// 我们可以定义: history: createWebHistory('XXX'),路由会自动在我们的页面路径前面加上"XXX", 例如: https://www.baidu.com/XXX/home
// console.log(import.meta.env.DEV)
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', redirect: '/404' },
{
path: '/home/:id',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
},
{
path: '/404',
name: '404',
component: Notfind
}
]
})
//全局前置守卫
router.beforeEach((to, from, next) => {
console.log('即将从', from.path, '跳转到', to.path)
next()
})
export default router
main.js 挂载路由
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
// router 路由功能
app.use(router)
app.mount('#app')
三. 路由链接和占位符
- < router-link>:路由链接,to属性则为点击此元素,需要切换的路由地址
- < router-view>:路由占位符,路由切换的视图展示的位置
四. 路由的重定向
简单理解: 用户本来要从 /a 访问 /b 但是加上路由重定向 /c 后, 用户可以直接无缝链接的从/a 访问到/c
const router = new VueRouter({
routes: [
{ path: '/b', redirect: '/c' }
]
})
路由重定向在Vue开发中主要用于以下场景:
- 默认入口跳转
当用户访问根路径/时自动导航到首页,避免空白页面。例如配置{ path: '/', redirect: '/home' }实现访问根目录时自动跳转至首页. - 旧路径迁移
网站改版后保留旧链接的有效性,将废弃路径重定向到新路径。如{ path: '/old-page', redirect: '/new-page' }可防止用户访问旧链接时出现404错误. - 权限控制
通过路由守卫实现条件跳转,例如未登录用户访问受限页面时重定向到登录页:
router.beforeEach((to) => {
if (to.meta.requiresAuth && !isLoggedIn) {
return '/login'
}
})
- 参数保留
动态路由中保持参数传递,例如将/user/123重定向到/profile/123时自动保留ID参数:
{
path: '/user/:id',
redirect: to => `/profile/${to.params.id}`
}
- 404处理
配置通配符路由捕获无效路径,如{ path: '/:pathMatch(.)', redirect: '/not-found' },提升用户体验
五. 路由跳转与参数传递
路由传参有两种方式:
- params 传参数
- query 传参数(类似于 URL中字段拼接(如 ?name=张三&age=20))
5.1 params 传参数(需要和router 规则中参数名一致)
// src/router/index.js
import Home from '../views/home.vue'
routes: [
{
path: '/home/:id',
name: 'home',
component: Home,
props: true // 将路径参数传递到展示组件的 props 中
}
]
页面跳转传参:
// app.vue
<!-- 直接在路径中传参 -->
<router-link :to="/home/123">首页123</router-link>
<!-- 使用路由名称和params 传值(注意:参数名要一致) -->
<router-link :to="{ name: 'home', params: { id: 12895 } }">首页跳转</router-link>
home.vue 页面获取 params参数
// home.vue
<template>
<div>home 页面,我是 home 页面 Hi</div>
<div>参数:{{ $route.params.id }}</div>
<div>prop参数:{{props.id }}</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const routeAA = useRoute()
console.log('=======打印', routeAA.params.id)
const props = defineProps({
id: {
type: String,
default() {
return ''
}
}
})
</script>
5.2 query 传参数
query 参数类似于 URL 中的查询字符串(如 ?name=张三&age=20),无需在路由规则中定义,直接传递即可:
// src/router/index.js
import About from '../views/about.vue'
routes: [
{
path: '/about',
name: 'about',
component: About
}
]
页面跳转传参:
// app.vue
<!-- query 传值 -->
<router-link :to="{ path: '/about', query: { keyword: '小明', age: '22' } }">
关于页面跳转
</router-link>
about.vue 页面获取数据
// about.vue
<template>
<div>参数1号:{{ $route.query.keyword }}</div>
<div>参数2号:{{ $route.query.age }}</div>
</template>
<script setup>
// 路由实例(处理路由参数的)
const route = useRoute()
console.log('打印keyword参数值:', route.query.keyword)
console.log('打印age参数值:', route.query.age)
// 路由器(处理页面跳转逻辑的)
const router = useRouter()
// 编程式路由跳转
router.push('/home')
</script>
编程式导航:
import { useRouter } from 'vue-router'
const router = useRouter()
router.push({ name: 'User', params: { id: 789 } })
router.push({ path: '/search', query: { keyword: 'pinia', page: 2 }})
<router-link :to="{ name: 'User', params: { id: 456 } }">用户 456</router-link>
<router-link :to="{ path: '/search', query: { keyword: 'vue', page: 1 } }">
router.push 的参数格式与 <router-link> 的 to 属性一致,可以是字符串路径,也可以是包含 path、name、params、query 等的对象。
五. 嵌套路由
- 在某一个路由规则中采用children来声明嵌套路由的规则
- 嵌套路由规则中的path不能以/开头,访问需使用/father/son的形式
路由层级与显示规则
路由配置结构决定了 <router-view /> 的显示内容:
const routes = [
{
path: '/parent',
component: ParentComponent,
children: [ // 配置子路由
// path 前面不要加 /
{ path: 'child1', component: Child1 },
{ path: 'child2', component: Child2 }
]
}
]
显示判断规则:
- 当访问 /parent 时,父组件的 <router-view /> 位置不会显示任何子组件
- 当访问 /parent/child1 时,父组件的 <router-view /> 位置会显示 Child1 组件
- 每个层级的 <router-view /> 只负责渲染当前路由级别下一级的组件
父子组件中的 router-view 位置
父组件模板需要包含 <router-view /> 作为子组件的容器
<template>
<div>
<h1>这是父组件</h1>
<!-- 子组件将在此处渲染 -->
<router-view></router-view>
</div>
</template>
六. 路由守卫
路由守卫用于在路由导航过程中进行拦截和控制,例如验证用户登录状态、权限检查等。
6.1 全局前置守卫
全局前置守卫会在每次路由跳转前触发,适用于全局的权限控制。
// router/index.js
import router from './index'
router.beforeEach((to, from, next) => {
// to:即将要进入的目标路由对象
// from:当前正要离开的路由对象
// next:函数,决定是否继续导航
console.log('即将从', from.path, '跳转到', to.path)
// 示例:判断用户是否登录,未登录则跳转到登录页
const isLogin = localStorage.getItem('isLogin') === 'true'
// 不需要登录的路由白名单
const whiteList = ['/login']
if (whiteList.includes(to.path)) {
// 白名单路由,直接放行
next()
} else {
// 判断时候登录
if (isLogin) {
// 已登录,放行
next()
} else {
// 未登录,跳转到登录页
next('/login')
}
}
})
next 函数的用法:
- next():继续导航到目标路由。
- next('/path') 或 next({ path: '/path' }):跳转到指定路由。
- next(false):中断当前导航。
6.2 组件内守卫包括 beforeRouteEnter、beforeRouteUpdate 和 beforeRouteLeave,定义在组件内部。
import { onBeforeRouteEnter, onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
// 进入组件前触发(此时组件实例还未创建,不能使用 this 或 setup 中的变量)
onBeforeRouteEnter((to, from, next) => {
console.log('即将进入个人资料页面')
// 可以通过 next 的回调函数访问组件实例
next(vm => {
// vm 是组件实例
console.log('组件实例:', vm)
})
})
// 组件更新时触发(例如路由参数变化但组件复用)
onBeforeRouteUpdate((to, from, next) => {
console.log('个人资料页面路由参数发生变化')
next()
})
// 离开组件时触发
onBeforeRouteLeave((to, from, next) => {
console.log('即将离开个人资料页面')
// 示例:提示用户是否保存修改
const isSave = confirm('是否保存修改?')
if (isSave) {
next()
} else {
// 取消离开
next(false)
}
})