Vue 路由:Vue Router 配置与导航守卫
在 Vue.js 单页应用开发中,页面跳转和权限控制是核心功能。Vue Router 作为官方管理器,负责将 URL 路径映射到组件,并控制导航流程。以下指南将详细介绍如何从零配置路由,并利用导航守卫实现精准的权限拦截。
一、 基础环境搭建与配置
开始之前,确保已创建 Vue 3 项目。以下步骤将引导你完成安装与核心配置。
-
执行安装命令。
在项目根目录下打开终端,运行以下命令安装 Vue Router 4:npm install vue-router@4 -
创建路由配置文件。
在src目录下新建一个名为router的文件夹,并在其中新建index.js文件。该文件将作为路由的入口。 -
定义路由映射表。
打开src/router/index.js,输入以下代码引入 Vue Router 并定义路由规则。这里我们将路径与具体的组件关联起来。import { createRouter, createWebHistory } from 'vue-router' import Home from '../views/Home.vue' import About from '../views/About.vue' // 定义路由数组 const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: About } ] // 创建路由实例 const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes }) // 导出路由实例 export default router -
挂载路由插件。
打开src/main.js,引入刚才创建的路由实例,并使用app.use方法将其注册到 Vue 应用中。import { createApp } from 'vue' import App from './App.vue' import router from './router' const app = createApp(App) app.use(router) app.mount('#app') -
设置路由出口。
打开src/App.vue,在模板中添加<router-view>组件。这是路由匹配到的组件渲染的地方。<template> <nav> <!-- 导航链接将在后面配置 --> </nav> <router-view/> </template>
二、 路由导航与参数传递
配置完成后,需要通过用户交互触发页面跳转。Vue Router 提供了声明式和编程式两种导航方式。
1. 声明式导航
-
使用
<router-link>组件。
该组件会被渲染为<a>标签。在App.vue或任何组件中,编写如下代码实现跳转:<router-link to="/">首页</router-link> <router-link to="/about">关于</router-link>
2. 编程式导航
当需要在逻辑代码中进行跳转(如表单提交成功后)时,使用路由实例的方法。
-
调用
router.push方法。
在<script setup>中获取路由实例并执行跳转:import { useRouter } from 'vue-router' const router = useRouter() const goHome = () => { router.push('/') }
3. 路由传参
在实际业务中,跳转往往伴随着数据传递。主要有两种方式:Params 和 Query。
| 传参方式 | URL 显示形式 | 特点说明 | 获取方式 |
|---|---|---|---|
| Query | /user?id=123 |
参数拼接在 URL 后面,类似 ?key=value,刷新不丢失 |
$route.query.id` |
| **Params** | `/user/123` | 参数作为路径的一部分,刷新页面可能会丢失(需配合动态路由) | `$route.params.id |
-
配置动态路由(用于 Params 传参)。
在src/router/index.js中修改路由配置,使用冒号:定义动态段:{ path: '/user/:id', name: 'User', component: () => import('../views/User.vue') // 懒加载写法 } -
发送参数。
在组件中编写跳转逻辑:// Query 传参 router.push({ path: '/user', query: { id: '123' } }) // Params 传参 router.push({ name: 'User', params: { id: '123' } }) -
接收参数。
在目标组件(如User.vue)中,使用useRoute获取数据:import { useRoute } from 'vue-router' const route = useRoute() console.log(route.params.id) console.log(route.query.id)
三、 导航守卫与权限控制
导航守卫主要用于通过跳转或取消的方式守卫导航。常见的场景是:用户未登录时禁止访问后台页面。
1. 全局前置守卫
这是最常用的守卫,注册在 router/index.js 中,对所有路由跳转进行拦截。
-
添加
beforeEach钩子。
在创建路由实例后,导出实例前,写入以下代码:// 假设我们有一个简单的函数检查 Token const isAuthenticated = () => { return !!localStorage.getItem('token') } router.beforeEach((to, from, next) => { // to: 即将进入的目标 // from: 当前导航正要离开的路由 // next: 必须调用该方法来 resolve 这个钩子 if (to.meta.requiresAuth && !isAuthenticated()) { // 如果需要登录但未登录,强制跳转到登录页 next({ name: 'Login' }) } else { // 否则正常放行 next() } }) -
配置路由元信息。
在需要权限的路由配置中,添加meta字段标记:{ path: '/admin', name: 'Admin', component: () => import('../views/Admin.vue'), meta: { requiresAuth: true } // 自定义字段,表示需要登录 }
2. 路由独享守卫
如果只需要对某一个特定路由进行拦截,可以直接在路由配置上定义 beforeEnter。
-
插入守卫字段。
在routes数组的具体路由对象中,添加beforeEnter:{ path: '/settings', component: Settings, beforeEnter: (to, from, next) => { // 仅在进入 /settings 路由时触发 if (confirm('确定要进入设置页吗?')) { next() } else { next(false) // 取消当前的导航 } } }
3. 组件内守卫
直接在组件内部定义路由逻辑,通常用于获取组件数据。
-
添加钩子函数。
在.vue文件的<script setup>中,使用onBeforeRouteLeave或onBeforeRouteUpdate:import { onBeforeRouteLeave } from 'vue-router' import { ref } from 'vue' const isSaved = ref(false) onBeforeRouteLeave((to, from, next) => { // 如果用户未保存修改,提示确认 if (!isSaved.value) { const answer = window.confirm('您有未保存的更改,确定要离开吗?') if (answer) { next() } else { next(false) } } else { next() } })
四、 导航解析流程解析
理解 Vue Router 的内部执行顺序对于排查路由问题至关重要。以下流程描述了从触发导航到最终渲染的完整过程。
当用户点击链接或调用 router.push 时,系统会按以下顺序执行检查:
-
触发导航。
导航被触发。 -
调用失活组件的
beforeRouteLeave。
如果当前页面有离开守卫,执行它。通常用于阻止未保存的修改丢失。 -
调用全局的
beforeEach。
检查全局前置守卫。如果所有守卫都调用了next(),则继续。 -
调用重用的组件内
beforeRouteUpdate。
如果当前组件是复用的(例如从/users/1跳到/users/2),执行更新守卫。 -
调用路由配置里的
beforeEnter。
执行路由独享守卫。 -
解析异步路由组件。
如果路由配置是懒加载的,加载对应的组件文件。 -
调用被激活的组件内
beforeRouteEnter。
执行进入组件的守卫。注意此时组件实例还没被创建,无法访问this。 -
调用全局的
beforeResolve。
导航确认前的最后一步。 -
导航被确认。
路由状态更新,URL 改变。 -
调用全局的
afterEach。
执行后置钩子。此时导航已经结束,可以用于更改页面标题或分析页面访问。 -
触发 DOM 更新。
Vue 渲染新的组件。 -
调用
beforeRouteEnter守卫中传给next的回调函数。
组件实例创建完成后,执行之前在beforeRouteEnter中传给next的回调函数,可以访问组件实例。
五、 路由懒加载与性能优化
为了减少首屏加载时间,应将不同路由对应的组件分割成不同的代码块,只有当路由被访问时才加载对应组件。
-
替换静态导入。
在src/router/index.js中,将原本的静态import语句修改为动态导入函数:// 修改前 // import Home from '../views/Home.vue' // 修改后 const Home = () => import('../views/Home.vue') const About = () => import('../views/About.vue') const Admin = () => import('../views/Admin.vue') const routes = [ { path: '/', name: 'Home', component: Home }, // ... ] -
打包观察。
当项目 运行npm run build时,你会注意到生成的dist目录中,各个组件被分离成单独的.js文件。浏览器只会在用户访问特定页面时才下载对应的文件。

暂无评论,快来抢沙发吧!