路由 Vue-router
安装:
npm i vue-router@4
1. 创建两个子组件Home.vue Mine.vue
<template>
<div style="background-color: red;">
<p>子组件-----Home</p>
</div>
</template>
<script setup lang="ts">
</script>
<template>
<div style="background-color: bisque;">
<p>子组件-----Mine</p>
</div>
</template>
<script setup lang="ts">
</script>
2. 创建路由配置
在 router/index.ts 文件中,定义你的路由配置:
常用配置参数:
“path” 用于配置访问路径
“name” 用于给该路由命名
“component” 表示需要映射的组件
“redirect”表示重定向
“children”用于路由嵌套
函数:
createRouter: 用于创建路由实例,接收一个配置对象作为参数。
参数:
history:用于定义路由模式,常用的有createWebHistory()和createWebHashHistory()。
routes:定义路由规则的数组。
createWebHistory: 创建 HTML5 模式的历史记录。
参数: base:可选,应用的基路径。
createWebHashHistory: 创建哈希模式的历史记录(URL 带有 #)。
参数: base:可选,应用的基路径。
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import Home from "../components/Home.vue";
import Mine from "../components/Mine.vue";
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/Mine',
name: 'Mine',
component: Mine
}
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
3. 在 Vue 实例中使用路由
在main.ts 文件中,导入并使用路由:
import router from './router'
const app = createApp(App);
app.use(router)
在APP.vue中使用路由功能:使用 <router-link> 进行导航,使用 <router-view> 显示匹配的组件
<template>
<router-link to="/">主页</router-link>
<router-link to="/Mine">我的页面</router-link>
<router-view></router-view>
</template>
4. 嵌套路由
实际项目中的应用界面通常由多层嵌套的组件组合而成。在配置嵌套路由时,在父路由中,增加children参数,添加对应的子路由
语法为:
routes: [{
path: '父路由路径',
component: 父组件,
children: [
{ path: '子路由路径1', component: 子组件1 },
{ path: '子路由路径2', component: 子组件2 }
]
}]
创建一个Home_child.vue
<template>
<div>
<p>Home中Child组件</p>
</div>
</template>
<script setup lang="ts">
</script>
配置中增加子路由:
{
path: '/',
name: 'Home',
component: Home,
children: [
{ path: 'child',
name: 'Home_child',
component: Home_child
}
]
},
Home.vue 使用路由
<template>
<div style="background-color: red;">
<p>子组件-----Home</p>
<router-link to="child">child</router-link>
<router-view></router-view>
</div>
</template>
<script setup lang="ts">
</script>
5. 动态路由
创建一个User.vue,并配置好动态路由,在User.vue中展示对应的数据
路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 route.params 的形式暴露出来。
6. 路由传参
方式一:路由属性配置传参,需进行组件的路由规则配置
直接在路由配置上加上:params进行传参
{
path: '/User/:username/id/:id',
name: 'UserParams',
component: User
},
<router-link to="/User/li/id/11">用户11</router-link>
//获取值
<p>{{ $route.params.username }}</p>
<p>{{ $route.params.id }}</p>
方式二:query方式传参,可以由name和path引入,无需配置组件的路由规则
{
path: '/User',
name: 'User',
component: User
}
router.push({path:"/User", query: {id: '123',username:'hello'}});
//获取值
<p>{{ $route.query.username }}</p>
<p>{{ $route.query.id }}</p>
方式三:params方式传参,只能由name引入,需进行组件的路由规则配置
{
path: '/User/:username/id/:id',
name: 'UserParams',
component: User
},
router.push({name:"UserParams", params: {username: '张三', id: '555'}});
//获取值
<p>{{ $route.params.username }}</p>
<p>{{ $route.params.id }}</p>
6. 动态添加路由
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
const routes: Array<RouteRecordRaw> = []
const router = createRouter({
history: createWebHistory(),
routes,
});
//动态添加路由
const homeRoute = {
path: '/',
name: 'Home',
component: ()=>import('../components/Home.vue'),
}
const mineRoute = {
path: '/Mine',
name: 'Mine',
component: ()=>import('../components/Mine.vue'),
}
const userRoute = {
path: '/User',
name: 'User',
component: ()=>import('../components/User.vue'),
}
const userComRoute = {
path: '/User/:username/id/:id',
name: 'UserParams',
component: ()=>import('../components/User.vue'),
}
//router.addRoute()动态添加,实际开发中根据if判断
router.addRoute(homeRoute);
router.addRoute(mineRoute);
router.addRoute(userRoute);
router.addRoute(userComRoute);
//添加子路由
router.addRoute('Home',{
path: 'child',
name: 'Home_child',
component: ()=>import("../components/Home_child.vue")
})
export default router;
7. 删除路由
删除路由有三种方式:
- 添加一个与之前路由一样名字的路由,之前的路由会被替代删除
- 调用删除函数
router.removeRoute('路由name') - 通过
addRoute()返回值回调
8. 导航守卫
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航
8.1 全局前置守卫
const router = createRouter({ ... })
router.beforeEach((to, from) => {
// ...
// 返回 false 以取消导航
return false
})
to: 即将要进入的目标from: 当前导航正要离开的路由
返回值:
false: 取消当前的导航。- 一个路由地址: 通过一个路由地址重定向到一个不同的地址,如同调用
router.push(),且可以传入诸如replace: true或name: 'home'之类的选项。它会中断当前的导航,同时用相同的from创建一个新导航。
router.beforeEach(async (to, from) => {
if (
// 检查用户是否已登录
!isAuthenticated &&
// ❗️ 避免无限重定向
to.name !== 'Login'
) {
// 将用户重定向到登录页面
return { name: 'Login' }
}
})
- 可选的第三个参数
next:
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
8.2 全局解析守卫
你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,因为它在每次导航时都会触发,不同的是,解析守卫刚好会在导航被确认之前、所有组件内守卫和异步路由组件被解析之后调用。
示例:根据路由在元信息中的 requiresCamera 属性确保用户访问摄像头的权限:
router.beforeResolve(async to => {
if (to.meta.requiresCamera) {
try {
await askForCameraPermission()
} catch (error) {
if (error instanceof NotAllowedError) {
// ... 处理错误,然后取消导航
return false
} else {
// 意料之外的错误,取消导航并把错误传给全局处理器
throw error
}
}
}
})
8.3 全局后置钩子
允许你在每次成功完成导航后执行一些额外的逻辑。
router.afterEach((to, from, failure) => {
})
-
to: 这是你即将到达的目标路由对象
-
from: 这是你离开的来源路由对象
-
failure: 这是导航失败的原因(如果有的话)
router.afterEach((to, from, failure)=>{
if(!failure) sendToAnalytics(to.fullPath)
})
function sendToAnalytics(path){
console.log(path)
}
可以做的一些事情:
- 记录数据:细心地跟踪用户的导航数据,帮助你了解他们的浏览轨迹。
- 更新页面标题:虽然更新标题更常见于 beforeEach 钩子,但有时在后置钩子中更新也能确保标题与内容的完美契合。
- 进行分析:执行各种后续分析任务,从用户行为到页面性能,一应俱全。
- 清理工作:完成导航后的清理工作,例如重置应用状态,让一切恢复整洁。
8.4 路由独享守卫
一个路由中配置的单独守卫
router.addRoute('Home',{
path: 'child',
name: 'Home_child',
beforeEnter: (to, from) => {
return false
},
component: ()=>import("../components/Home_child.vue")
})
beforeEnter 守卫 只在进入路由时触发,不会在 params、query 或 hash 改变时触发
8.5 组件内守卫
在路由组件内直接定义路由导航守卫
<script setup lang="ts">
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router';
onBeforeRouteUpdate(async (to, from) => {
//守卫在当前路由发生改变时触发,例如 : 从 /c/100 跳转到 /c/200
})
onBeforeRouteLeave((to, from) => {
//守卫在当前路由离开时触发,例如 :从 /c 跳转到 /a
})
</script>