五,Vue3集成Vue-Router实现路由跳转

https://router.vuejs.org/

客户端路由的作用是在单页应用 (SPA) 中将浏览器的 URL 和用户看到的内容绑定起来。当用户在应用中浏览不同页面时,URL 会随之更新,但页面不需要从服务器重新加载。

Vue Router 基于 Vue 的组件系统构建,你可以通过配置路由来告诉 Vue Router 为每个 URL 路径显示哪些组件。

入门 | Vue Router

如何定义新的路由

找到router文件夹里面的index.js文件

https://bu.dusays.com/2024/10/30/672248641e2bc.png

路由跳转

使用方法一:使用类似于a标签的方式去跳转

<RouterLink to="/test">go to test</RouterLink>

使用方法二:



<template>

<el-button type="primary" @click="router.push('/')">go to home</el-button>
</template>

<script setup>

import router from "@/router/index.js";


</script>


  • push router.push(‘/test’) 跳转后可以返回
  • replace router.replace(‘/test’) 跳转后无法返回

路由传参(很重要)

我们使用的都是 query 类型的参数(因为简单容易理解)

传参:router.push(‘/test?id=1’)

获取参数:通过 router.currentRoute.value.query 获取到 query 对象 { id: 1 }

现在你拥有了两个界面,home和test对不对?

我在home页面跳转test页面的时候,获取到id

<template>
<div>
<el-button type="primary" @click="router.push('/test?id=1')">跳转并且传输参数</el-button>
</div>
</template>
<script setup>

import router from "@/router/index.js";
</script>

可以看到参数已经传递过来了

https://bu.dusays.com/2024/10/30/672248640dfb2.png

那么,现在test怎么拿到这个id的值?



<template>

<el-button type="primary" @click="router.push('/')">go to home</el-button>
<el-button type="success" @click="id">go to test</el-button>
<!-- 第二种传参的方法 -->
<el-button type="success" @click="showId">show id </el-button>
</template>

<script setup>
import { reactive } from "vue";
import router from "@/router/index.js";

const data = reactive({
id:router.currentRoute.value.query.id
})
const id = () => {
router.push({
path: '/',query: {id: 2,name:vinicuna}
})
}
// 具体方法,内部,并且同时传输两个参数
const showId = () => {
alert(data.id)
}
</script>


嵌套路由

在父级的页面通过 可以展现子级页面的内容

先我们对路由进行重定向操作

import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{path:'/',redirect:'/manage'},
{path: '/manage', name: 'manage', component: () => import('../views/manage.vue'),
children: []}
// 这里的children是一个对象的数组,跟'/manage'是平级的,现在我们往children里面填充路由对象数据
]
})

export default router

填充后的数据是这样的:

注意:你的子级页面的router会被自动加上’/‘,所以需要去掉原本的’/‘

import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{path:'/',redirect:'/manage'},
{path: '/manage', name: 'manage', component: () => import('../views/manage.vue'),
children: [
{ path: 'home', name: 'home', component: () => import('../views/Home.vue')},
{path: 'test', name: 'test', component: () => import('../views/test.vue')},
// 注意:你的子级页面的router会被自动加上'/',所以需要去掉原本的'/'
]}

]
})

export default router

接下来,在父级页面通过

<RouterView />
<!-- 去使用子级页面 -->

完整代码如下:

<script setup>

</script>

<template>
这是一个父级页面,可以嵌套多个子级页面
<RouterView/>
</template>

<style scoped>

</style>

路由守卫

在Vue 3中,路由守卫是一种控制导航行为的机制,用于在用户访问不同路由之前、之中或之后执行特定逻辑。路由守卫的作用主要是确保用户只能访问他们有权限的页面,或者在特定条件下控制页面导航。Vue 3 中的路由守卫可以分为以下几种类型:

1. 全局守卫

全局守卫应用于所有路由,可以统一处理权限控制、登录验证等需求。

  • beforeEach:在每次导航触发之前调用。可以用来验证用户权限或判断用户是否登录等。
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated) {
next('/login'); // 未登录时跳转到登录页
} else {
next(); // 放行
}
});
  • beforeResolve:在导航被确认之前,同时在所有组件内守卫和异步路由组件解析完成后调用,通常用于处理数据请求。
  • afterEach:在导航完成后调用,通常用于一些页面统计等不影响导航的逻辑。

2. 路由独享守卫

在定义单个路由时,可以使用beforeEnter来定义路由独享守卫,它仅在进入该路由时生效。

const routes = [
{
path: '/dashboard',
component: Dashboard,
beforeEnter: (to, from, next) => {
if (userIsAdmin) {
next();
} else {
next('/login'); // 如果不是管理员,跳转到登录页
}
}
}
];

3. 组件内守卫

在单个组件内定义的守卫,能够直接访问组件实例,可以用于需要组件实例的场景,比如路由切换时确认保存数据等。

  • beforeRouteEnter:在进入路由之前调用,但无法直接访问组件实例。
beforeRouteEnter(to, from, next) {
next(vm => {
// vm为当前组件实例
});
}
  • beforeRouteUpdate:在同一路由被复用时调用,可以访问当前组件实例。
  • beforeRouteLeave:在离开当前路由时调用,常用于确认数据保存或取消操作。

路由守卫的用途

  1. 权限控制:阻止未授权用户进入某些页面。
  2. 登录验证:确保用户在访问特定页面前已登录。
  3. 数据加载:在页面切换之前加载必要数据,提升用户体验。
  4. 导航确认:用户在未保存数据时离开页面时的确认弹窗。

使用方法之一:

利用meta去修改页面的title

import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{path:'/',redirect:'/manage'},
{path: '/manage', name: 'manage',meta:{title:'父级页面'}, component: () => import('../views/manage.vue'),
children: [
{ path: 'home', name: 'home', meta:{title:'主页'}, component: () => import('../views/Home.vue')},
{path: 'test', name: 'test', meta:{title:'测试页面'},component: () => import('../views/test.vue')},
]}

]
})

// from:将要进行跳转的当前route对象 (跳转前的一些操作)
// to: 跳转后route对象 (跳转后的一些操作)
// next(): 调用该方法后, 才能进入下一个钩子
router.beforeEach((to, from, next) => {
document.title = to.meta.title;
next()
})
export default router

404页面的设置

首先去找一个404页面的图片之类的,放到本地

比如我就喜欢这个,这个也是我博客有图片显示不出来的时候,替换的图片

https://bu.dusays.com/2024/10/30/67224864127a8.jpg

保存到本地,vue/src/assets/imgs路径

https://bu.dusays.com/2024/10/30/6722486410c95.png

再去写一个vue组件,跟Home,test,manage同理

这个就叫404.vue

<script setup>

import router from "@/router/index.js";
</script>

<template>
<div style="text-align: center">
<img src="@/assets/imgs/404.jpg" alt="页面丢失">
</div>
<div style="text-align: center;font-size: 200px">
<el-button type="primary" @click="router.push('/manage/home')">返回首页</el-button>
</div>
</template>

<style scoped>

</style>

2.去定义404路由

import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{path:'/',redirect:'/manage'},
{path: '/manage', name: 'manage',meta:{title:'父级页面'}, component: () => import('../views/manage.vue'),
children: [
{ path: 'home', name: 'home', meta:{title:'主页'}, component: () => import('../views/Home.vue')},
{path: 'test', name: 'test', meta:{title:'测试页面'},component: () => import('../views/test.vue')},
]},
{path: '/404', name: '404', meta:{title:'404页面'}, component: () => import('../views/404.vue')},


]
})

// from:将要进行跳转的当前route对象 (跳转前的一些操作)
// to: 跳转后route对象 (跳转后的一些操作)
// next(): 调用该方法后, 才能进入下一个钩子
router.beforeEach((to, from, next) => {
document.title = to.meta.title;
next()
})
export default router

路由错误的时候,全部统一返回404界面

{ path: '/:pathMatch(.*)', redirect: '/404' }

完整的代码

import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{path:'/',redirect:'/manage'},
{path: '/manage', name: 'manage',meta:{title:'父级页面'}, component: () => import('../views/manage.vue'),
children: [
{ path: 'home', name: 'home', meta:{title:'主页'}, component: () => import('../views/Home.vue')},
{path: 'test', name: 'test', meta:{title:'测试页面'},component: () => import('../views/test.vue')},
]},
{path: '/404', name: '404', meta:{title:'404页面'}, component: () => import('../views/404.vue')},
{ path: '/:pathMatch(.*)', redirect: '/404' }//路由重定向,这个必须写在最下面,当路由没有匹配到上面的任何一个的时候将会调用这个路由

]
})

// from:将要进行跳转的当前route对象 (跳转前的一些操作)
// to: 跳转后route对象 (跳转后的一些操作)
// next(): 调用该方法后, 才能进入下一个钩子
router.beforeEach((to, from, next) => {
document.title = to.meta.title;
next()
})
export default router