个人技术分享

Vue Router 是 Vue 官方的客户端路由解决方案,可以通过配置路由来告诉 Vue Router 为每个 URL 路径显示哪些组件。

1. Vue3 中使用 vue-router


安装

npm install vue-router@4

创建路由配置文件

新建 router/index.js 文件按用来统一管理路由配置。

// router/index.js
import { createRouter, createWebHistory } from "vue-router";

const router = createRouter({
  history: createWebHistory(),
  routes: [
	{
	  path: '/',
	  component: () => import("@/views/Home"),
	},
	{
	  path: '/user',
	  component: () => import("@/views/User"),
	}
  ]
})


export default router;

在 main.js 中注册路由

// main.js

import { createApp } from 'vue'
import router from './router'
import App from './app.vue'

const app = createApp(App)
app.use(router).mount('#app')

在组件中使用路由

<!-- App.vue -->
<template>
  <nav>
    <router-link to="/">首页</router-link>
    <router-link to="/user">用户</router-link>
  </nav>
  <main>
    <router-view />
  </main>

</template>

2. 路由配置


动态路由匹配

// router/index.js

const routes = [
  {
    path: '/user/:id',
    component: User,
  }
]

路径参数用冒号 : 表示。当一个路由被匹配时(/user/123),它的 params 的值可以使用 useRoute() 钩子函数获取。

<!-- User.vue -->
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute();
console.log(route.params);		// {id: 123}
</script>

使用带有参数的路由时需要注意的是,当用户从 /users/122 导航到 /users/123 时,相同的组件实例将被重复使用,从而组件的生命周期钩子不会被调用。

要对同一个组件中参数的变化做出响应的话,可以使用 watch 监听 route.params。

嵌套路由

const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      {        
        path: '',				// 当 /user/:id 匹配成功
        component: UserHome,	// UserHome 将被渲染到 User 的 <router-view> 内部
      },
      {        
        path: 'posts',			// 当 /user/:id/posts 匹配成功
        component: UserPosts,	// UserPosts 将被渲染到 User 的 <router-view> 内部
      },
    ],
  },
]

注意:子路由的 path 属性中不可以带 /,否则无法匹配。

<!-- User.vue -->
<template>
  <div>{{ route.params.id }}</div>
  <router-view />
</template>

3. 路由导航


<script setup>
import { useRouter } from 'vue-router'

const router = useRouter()
router.push()		// 导航
router.replace()	// 替换
router.go(1)		// 返回上一条记录
</script>

传参

const username = 'eduardo'

router.push(`/user/${username}`) 		// -> /user/eduardo

router.push({ path: `/user/${username}` }) 	// -> /user/eduardo

// 命名路由
router.push({ name: 'user', params: { username } }) 	// -> /user/eduardo

// `params` 不能与 `path` 一起使用
router.push({ path: '/user', params: { username } }) 	// -> /user

// 带查询参数
router.push({ path: '/user', query: { username } })		// -> /user?username=eduardo

4. 导航守卫

vue-router 提供的导航守卫主要用于在路由导航过程中添加一些额外的逻辑,如权限验证、数据获取等。它允许你在路由发生变化的不同阶段插入自定义的代码片段,从而控制路由的跳转和取消。

全局前置守卫

router.beforeEach 用于在路由跳转前执行一些逻辑,例如身份验证。当一个导航触发时,全局前置守卫按照创建顺序调用。

// router/index.js
const router = createRouter({ ... })

router.beforeEach(async (to, from) => {
  if (!isAuthenticated && to.path !== '/login'){
    return '/login'				// 检查用户是否已登录,否则重定向到登录页面
  }
})
  • 参数
    • to:即将要进入的目标
    • from:当前导航正要离开的路由
  • 返回值
    • false:取消当前的跳转
    • 路由地址:跳转到指定路由
    • 不返回或返回 true / undefined:进行默认导航

全局解析守卫

router.beforeResolve 在导航被确认之前、所有组件内守卫和异步路由组件被解析之后调用。适用于在组件渲染之前获取必要的数据。例如,你可能想要根据路由参数从服务器获取数据,并在组件渲染之前将数据传递给组件。

全局后置钩子

router.afterEach 在导航完成后触发。它不改变导航本身,不能取消或重定向导航,而通常用于执行一些与导航结果相关的操作,如追踪、分析或调试。例如,你可以在这里记录页面访问统计信息。