【Vue工程】005-Vue Router
文章目录
- 【Vue工程】005-Vue Router
- 一、概述
- 1、Slogan
- 2、官网
- 3、参考文章
- 二、安装
- 三、基本使用
- 1、定义路由
- 2、创建路由实例
- 3、在 `main.ts` 注册路由
- 4、在 `App.vue` 定义路由出口
- 四、嵌套路由
- 1、修改路由
- 2、定义嵌套路由出口
- 五、配置404页面
- 六、声明式、编程式导航
- 1、声明式导航(在模板中进行路由跳转)
- 2、编程式导航(组合式API)
- 七、重定向
- 八、路由跳转传参
- 1、动态路由匹配
- 路由配置
- 当前组件:传参
- 跳转目标组件:接收参数
- 运行结果
- 路由嵌套刷新页面策略
- 2、查询参数
- 路由配置
- 当前组件:传参
- 跳转目标组件:接收参数
- 运行结果
- 九、导航守卫
- 1、全局前置守卫
- 2、路由独享守卫
- 3、组件内守卫
- 十、路由元信息
- 十一、router-link
- 十二、动态路由
- 1、修改 `router/routes.ts`
- 2、修改 `pages/login.vue`
- 3、修改 `App.vue`
一、概述
1、Slogan
为 Vue.js 提供富有表现力、可配置的、方便的路由。
2、官网
https://router.vuejs.org/zh/
3、参考文章
人家写得太好,没多少可改的,部分内容直接摘录。
https://juejin.cn/post/7223779544368627773
二、安装
pnpm add vue-router
三、基本使用
1、定义路由
创建文件 src/router/routes.ts
const routes = [
{
path: '/',
component: () => import('@/pages/login.vue'),
},
{
path: '/home',
component: () => import('@/pages/home.vue'),
},
];
export default routes;
src/pages/login.vue
<template>
<div>登录</div>
</template>
<script lang="ts" setup></script>
<style scoped></style>
src/pages/home.vue
<template>
<div>home</div>
</template>
<script lang="ts" setup></script>
<style scoped></style>
2、创建路由实例
创建文件 src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import routes from './routes';
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
3、在 main.ts
注册路由
import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
// 导入路由
import router from './router';
const app = createApp(App);
// 注册路由
app.use(router);
app.mount('#app');
4、在 App.vue
定义路由出口
<template>
<!-- 写法一-->
<!-- <router-view v-slot="{ Component }">-->
<!-- <transition name="fade" mode="out-in">-->
<!-- <component :is="Component" />-->
<!-- </transition>-->
<!-- </router-view>-->
<!-- 写法二-->
<router-view />
</template>
<style></style>
四、嵌套路由
在 App.vue 中定义的 router-view,这是顶层的出口,渲染最高级路由匹配到的组件。
如果要实现登录之后左侧菜单栏不变,右侧随路由的切换变化显示的内容,需使用嵌套路由。
1、修改路由
修改文件 src/router/routes.ts
其他 vue 文件此处省略。
const routes = [
{
path: "/login",
component: () => import("@/pages/login.vue"),
},
{
path: "/home",
component: () => import("@/pages/home.vue"),
children: [
{
path: "/home/user",
component: () => import("@/pages/user.vue"),
},
{
path: "/home/manage",
component: () => import("@/pages/manage.vue"),
},
],
},
];
export default routes;
2、定义嵌套路由出口
修改 src/pages/home.vue
<template>
<div>
菜单栏
<router-view />
</div>
</template>
五、配置404页面
修改router/routes.ts
const routes = [
{
path: '/',
component: () => import('@/pages/login.vue'),
},
{
path: '/home',
component: () => import('@/pages/home.vue'),
},
{
path: '/:pathMatch(.*)*',
component: () => import('@/pages/notFound.vue'),
},
];
export default routes;
六、声明式、编程式导航
1、声明式导航(在模板中进行路由跳转)
<router-link to="/home"> 跳转home </router-link>;
2、编程式导航(组合式API)
<script setup lang="ts">
import { useRouter } from 'vue-router';
const router = useRouter();
const handleManage = () => {
router.push('/home/manage');
};
</script>
七、重定向
场景:在嵌套路由中,当访问 / 时想重定向到/home
修改router/routes.ts
{
path: '/home',
component: () => import('@/pages/home.vue'),
redirect: '/home/user', // 新增
children: [
{
path: '/home/user',
component: () => import('@/pages/user.vue'),
},
{
path: '/home/manage',
component: () => import('@/pages/manage.vue'),
},
],
},
八、路由跳转传参
我的另一篇文章:https://blog.csdn.net/qq_29689343/article/details/130172191
1、动态路由匹配
路由配置
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'Hello',
component: Hello,
},
{
path: '/next-page/:message',
name: 'NextPage',
component: NextPage,
},
];
当前组件:传参
<template>
<button @click="toNextPage">toNextPage</button>
</template>
<script setup lang="ts">
import {useRouter} from 'vue-router';
// 得到 router 对象
const router = useRouter();
// 页面跳转
const toNextPage = () => {
router.push({name: 'NextPage', params: {message: "基本字符串"}});
}
</script>
跳转目标组件:接收参数
<template>
<h1>NextPage</h1>
<h1>基本数据:{{ route.params.message }}</h1>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
import {onMounted} from "vue";
const route = useRoute();
</script>
运行结果
路由嵌套刷新页面策略
<template>
<h1>NextPage</h1>
<h1 :key="thisVersion">基本数据:{{ route.params.message }}</h1>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
import {ref, watch} from "vue";
const route = useRoute();
// 当前版本
const thisVersion = ref(0);
// 监听参数变化,更新版本,刷新组件(大致写法,未测试)
watch(() => route.params.message, () => {
thisVersion.value ++;
})
</script>
2、查询参数
路由配置
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'Hello',
component: Hello,
},
{
path: '/next-page',
name: 'NextPage',
component: NextPage,
},
];
当前组件:传参
<template>
<button @click="toNextPage">toNextPage</button>
</template>
<script setup lang="ts">
import {useRouter} from 'vue-router';
// 得到 router 对象
const router = useRouter();
// 页面跳转
const toNextPage = () => {
router.push({name: 'NextPage', query: {message: "基本字符串", name: "訾博"}});
}
</script>
跳转目标组件:接收参数
<template>
<h1>NextPage</h1>
<h1>基本数据:{{ route.query.message }}</h1>
<h1>基本数据:{{ route.query.name }}</h1>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
const route = useRoute();
</script>
运行结果
九、导航守卫
1、全局前置守卫
使用场景:做登录判断,未登陆用户跳转到登录页
修改router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import routes from './routes';
const router = createRouter({
history: createWebHistory(),
routes,
});
router.beforeEach((to, from) => {
if (to.path === '/login') {
// 在登录页做清除操作,如清除token等
}
if (!localStorage.getItem('token') && to.path !== '/login') {
// 未登陆且访问的不是登录页,重定向到登录页面
return '/login';
}
});
export default router;
2、路由独享守卫
使用场景:部分页面不需要登录,部分页面需要登录才能访问
修改 router/routes.ts
// 权限校验
const auth = () => {
if (!localStorage.getItem('token')) {
// 未登陆,重定向到登录页面
return '/login';
}
};
// 路由配置
const routes = [
{
path: '/',
component: () => import('@/pages/login.vue'),
},
{
path: '/home',
component: () => import('@/pages/home.vue'),
beforeEnter: auth,
},
];
export default routes;
3、组件内守卫
使用场景:预防用户在还未保存修改前突然离开。该导航可以通过返回 false 来取消
<script setup lang="ts">
import { onBeforeRouteLeave } from 'vue-router';
// 与 beforeRouteLeave 相同,无法访问 `this`
onBeforeRouteLeave((to, from) => {
const answer = window.confirm('确定离开吗');
// 不再跳转
if (!answer) return false;
});
</script>
十、路由元信息
将自定义信息附加到路由上,例如页面标题,是否需要权限,是否开启页面缓存等
使用情景:使用路由元信息+全局前置守卫实现部分页面不需要登录,部分页面需要登录才能访问
修改router/routes.ts
const routes = [
{
path: "/home",
component: () => import("@/pages/home.vue"),
redirect: "/home/user",
children: [
{
path: "/home/user",
component: () => import("@/pages/user.vue"),
},
{
path: "/home/manage",
component: () => import("@/pages/manage.vue"),
meta: {
title: "管理页", // 页面标题
auth: true, // 需要登录权限
},
},
],
},
];
修改 router/index.ts
router.beforeEach((to, from) => {
if (!localStorage.getItem("token") && to.meta.auth) {
// 此路由需要授权,请检查是否已登录
// 如果没有,则重定向到登录页面
return {
path: "/login",
// 保存我们所在的位置,以便以后再来 (因为跳转到登录页面,用户登录之后还需跳转回来)
query: { redirect: to.fullPath },
};
}
});
十一、router-link
router-link 组件默认为a标签,在vue router 3.x中,可通过tag属性更改标签名,event属性更改事件名
在vue router 4.x中,这两个属性已被删除,通过作用域插槽(子组件给父组件传值的插槽)实现自定义导航标签
示例:将导航标签改为div,且需双击触发
<router-link v-slot="{ href, navigate, isExactActive }" to="/home/user" custom>
<div :class="{ active: isExactActive }" :href="href" @dblclick="navigate">跳转user</div>
</router-link>
十二、动态路由
与动态路由匹配不同,动态路由是手动添加路由表中没有的路由,通常用在权限校验中,如果没有该权限,直接访问该路由失败
1、修改 router/routes.ts
const routes = [
{
path: "/login",
component: () => import("@/pages/login.vue"),
},
{
path: "/register/:plan",
component: () => import("@/pages/register.vue"),
},
{
path: "/home",
name: "Home", // 增加 name,动态路由通过 name 挂载到该子路由下
component: () => import("@/pages/home.vue"),
redirect: "/home/user",
children: [
{
path: "/home/user",
component: () => import("@/pages/user.vue"),
},
],
},
{
path: "/:pathMatch(.*)*",
component: () => import("@/pages/notFound.vue"),
},
];
// 将 /home/manage 拆出来
export const manageRoute = {
path: "/home/manage",
component: () => import("@/pages/manage.vue"),
};
export default routes;
2、修改 pages/login.vue
<script setup lang="ts">
localStorage.setItem('role', 'admin'); //在登录页存储用户等级
</script>;
3、修改 App.vue
如果 localStorage.getItem(‘role’) 的值不为 admin ,直接访问 /home/manage,会返回 404 页面
<script setup lang="ts">
import { watch } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { manageRoute } from '@/router/routes';
const router = useRouter();
const route = useRoute();
watch(route, async (newVal) => {
const role = localStorage.getItem('role');
if (role && role === 'admin') {
// admin 直接访问
router.addRoute('Home', manageRoute);
// 防止页面刷新,路由丢失
if (newVal.fullPath === '/home/manage') {
// 会返回404页面
await router.replace('/home/manage');
}
}
});
</script>