Vue路由深度解析:Vue Router与导航守卫

Vue路由深度解析:Vue Router与导航守卫

一、Vue Router基础与安装配置

1. Vue Router核心概念

Vue Router是Vue.js官方的路由管理器,主要功能包括:

  • 嵌套路由映射
  • 模块化的路由配置
  • 路由参数、查询、通配符
  • 细粒度的导航控制
  • 自动激活的CSS类链接
  • HTML5 history模式或hash模式
  • 可定制的滚动行为

2. 安装与基本配置

安装Vue Router

npm install vue-router@4
# 或
yarn add vue-router@4

基础配置示例

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'const routes = [{path: '/',name: 'home',component: HomeView},{path: '/about',name: 'about',// 路由级代码拆分component: () => import('../views/AboutView.vue')}
]const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes
})export default router

在main.js中引入

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'const app = createApp(App)
app.use(router)
app.mount('#app')

二、路由模式与路由配置详解

1. 路由模式对比

模式特点示例
Hash模式使用URL hash模拟完整URLhttp://example.com/#/about
History模式使用HTML5 History APIhttp://example.com/about
Memory模式不修改URL,适合非浏览器环境(如Electron)无URL变化

配置示例

import { createWebHashHistory,  // Hash模式createWebHistory,     // History模式createMemoryHistory   // Memory模式
} from 'vue-router'const router = createRouter({history: createWebHistory(), // 推荐生产环境使用// history: createWebHashHistory(), // 兼容性更好// history: createMemoryHistory(), // 非浏览器环境routes
})

2. 动态路由与参数传递

动态路由配置

const routes = [// 动态字段以冒号开始{path: '/user/:id',name: 'user',component: UserView},// 可匹配/user/123或/user/456{path: '/user/:id/posts/:postId',component: UserPostView}
]

参数获取方式

<template><!-- 在模板中直接使用 --><div>用户ID: {{ $route.params.id }}</div>
</template><script setup>
import { useRoute } from 'vue-router'// 在setup中使用
const route = useRoute()
console.log(route.params.id)
</script><script>
// 在Options API中使用
export default {created() {console.log(this.$route.params.id)}
}
</script>

3. 嵌套路由与命名视图

嵌套路由配置

const routes = [{path: '/user/:id',component: UserLayout,children: [{path: '', // 默认子路由component: UserProfile},{path: 'posts',component: UserPosts},{path: 'settings',component: UserSettings}]}
]

命名视图(多路由出口)

const routes = [{path: '/',components: {default: HomeView, // 默认出口sidebar: SidebarView, // <router-view name="sidebar">footer: AppFooter  // <router-view name="footer">}}
]

三、导航守卫全面解析

1. 导航守卫类型与执行流程

完整的导航解析流程

  1. 导航被触发
  2. 调用beforeRouteLeave守卫(组件内)
  3. 调用全局beforeEach守卫
  4. 在重用的组件里调用beforeRouteUpdate守卫(组件内)
  5. 调用路由配置里的beforeEnter守卫
  6. 解析异步路由组件
  7. 在被激活的组件里调用beforeRouteEnter(组件内)
  8. 调用全局beforeResolve守卫
  9. 导航被确认
  10. 调用全局afterEach钩子
  11. 触发DOM更新
  12. 调用beforeRouteEnter守卫中传给next的回调函数

2. 全局守卫

// router/index.js// 全局前置守卫
router.beforeEach((to, from, next) => {console.log('全局前置守卫', to, from)// 必须调用next()继续导航next()
})// 全局解析守卫
router.beforeResolve((to, from, next) => {console.log('全局解析守卫', to, from)next()
})// 全局后置钩子
router.afterEach((to, from) => {console.log('全局后置钩子', to, from)// 不需要next函数
})

3. 路由独享守卫

const routes = [{path: '/admin',component: AdminView,beforeEnter: (to, from, next) => {// 仅在此路由触发if (isAdmin()) next()else next('/login')}}
]

4. 组件内守卫

<script>
export default {beforeRouteEnter(to, from, next) {// 在渲染该组件的对应路由被验证前调用// 不能获取组件实例 `this`next(vm => {// 通过 `vm` 访问组件实例console.log(vm.someData)})},beforeRouteUpdate(to, from) {// 当前路由改变,但是该组件被复用时调用// 可以访问组件实例 `this`this.fetchData(to.params.id)},beforeRouteLeave(to, from) {// 导航离开该组件的对应路由时调用// 可以访问组件实例 `this`const answer = window.confirm('确定要离开吗?未保存的更改将会丢失')if (!answer) return false}
}
</script>

5. 导航守卫实战:权限控制

// router/index.js
import { useAuthStore } from '@/stores/auth'const routes = [{path: '/',name: 'home',component: HomeView,meta: { requiresAuth: false }},{path: '/dashboard',name: 'dashboard',component: DashboardView,meta: { requiresAuth: true,roles: ['admin', 'editor'] }},{path: '/admin',name: 'admin',component: AdminView,meta: { requiresAuth: true,roles: ['admin'] }}
]router.beforeEach(async (to, from, next) => {const authStore = useAuthStore()const isAuthenticated = authStore.isAuthenticatedconst userRole = authStore.user?.role || 'guest'// 检查路由是否需要认证if (to.meta.requiresAuth && !isAuthenticated) {return next({ name: 'login', query: { redirect: to.fullPath } })}// 检查路由角色权限if (to.meta.roles && !to.meta.roles.includes(userRole)) {return next({ name: 'forbidden' })}// 如果用户已登录但要去登录页,重定向到首页if (to.name === 'login' && isAuthenticated) {return next({ name: 'home' })}next()
})

四、路由高级特性

1. 路由元信息与过渡动画

路由元信息配置

const routes = [{path: '/posts',component: PostsLayout,meta: { requiresAuth: true,transition: 'slide-left' },children: [{path: 'new',component: NewPost,meta: { transition: 'slide-up',requiresAdmin: true }}]}
]

动态过渡效果

<template><router-view v-slot="{ Component, route }"><transition :name="route.meta.transition || 'fade'"><component :is="Component" /></transition></router-view>
</template><style>
.fade-enter-active,
.fade-leave-active {transition: opacity 0.3s ease;
}.fade-enter-from,
.fade-leave-to {opacity: 0;
}.slide-left-enter-active,
.slide-left-leave-active {transition: transform 0.3s ease;
}.slide-left-enter-from {transform: translateX(100%);
}.slide-left-leave-to {transform: translateX(-100%);
}.slide-up-enter-active,
.slide-up-leave-active {transition: transform 0.3s ease;
}.slide-up-enter-from {transform: translateY(100%);
}.slide-up-leave-to {transform: translateY(-100%);
}
</style>

2. 滚动行为控制

const router = createRouter({history: createWebHistory(),routes,scrollBehavior(to, from, savedPosition) {// 返回滚动位置对象if (savedPosition) {return savedPosition // 浏览器前进/后退时恢复位置}if (to.hash) {return {el: to.hash, // 滚动到锚点behavior: 'smooth' // 平滑滚动}}if (to.meta.scrollToTop) {return { top: 0 } // 新路由滚动到顶部}// 默认不改变滚动位置}
})

3. 路由懒加载与分包

基础懒加载

const routes = [{path: '/about',component: () => import('../views/AboutView.vue')}
]

自定义分包

const routes = [{path: '/admin',component: () => import(/* webpackChunkName: "admin" */ '../views/AdminView.vue'),children: [{path: 'dashboard',component: () => import(/* webpackChunkName: "admin" */ '../views/AdminDashboard.vue')}]},{path: '/user/:id',component: () => import(/* webpackChunkName: "user" */ '../views/UserView.vue')}
]

4. 动态路由API

添加路由

router.addRoute({path: '/new-route',name: 'newRoute',component: () => import('../views/NewView.vue')
})// 添加到现有路由的子路由
router.addRoute('parentRoute', {path: 'child',component: () => import('../views/ChildView.vue')
})

删除路由

// 通过名称删除
router.removeRoute('routeName')// 通过添加返回的回调删除
const removeRoute = router.addRoute(routeConfig)
removeRoute() // 删除路由

检查路由

// 检查路由是否存在
router.hasRoute('routeName')// 获取所有路由记录
router.getRoutes()

五、常见问题与最佳实践

1. 常见问题解决方案

问题1:路由重复跳转报错

// 统一处理导航错误
router.onError((error) => {if (error.message.includes('Avoided redundant navigation')) {// 忽略重复导航错误} else {// 处理其他导航错误}
})

问题2:动态路由刷新404

  • History模式需要服务器配置支持
  • Nginx配置示例:
    location / {try_files $uri $uri/ /index.html;
    }
    

问题3:路由组件不更新

// 使用beforeRouteUpdate或监听$route
watch(() => route.params.id,(newId) => {fetchData(newId)}
)

2. 最佳实践建议

  1. 路由组织

    • 按功能模块组织路由文件
    • 使用路由元信息(meta)存储权限、标题等信息
    • 对大型项目考虑自动导入路由
  2. 性能优化

    • 合理使用路由懒加载
    • 对频繁访问的路由考虑预加载
    • 避免在导航守卫中进行繁重操作
  3. 安全实践

    • 始终验证前端路由权限
    • 敏感路由应在后端再次验证
    • 使用路由独享守卫处理特殊权限
  4. 开发体验

    • 为路由添加name属性方便跳转
    • 使用路由元信息管理页面标题
    • 实现进度条提升用户体验

六、综合实战:企业级路由方案

1. 完整路由配置示例

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import NProgress from 'nprogress'const routes = [{path: '/',name: 'home',component: () => import('@/views/HomeView.vue'),meta: {title: '首页',requiresAuth: false,cache: true}},{path: '/login',name: 'login',component: () => import('@/views/LoginView.vue'),meta: {title: '登录',guestOnly: true}},{path: '/dashboard',name: 'dashboard',component: () => import('@/views/DashboardView.vue'),meta: {title: '仪表盘',requiresAuth: true}},{path: '/admin',name: 'admin',component: () => import('@/views/layouts/AdminLayout.vue'),meta: {title: '管理后台',requiresAuth: true,roles: ['admin']},children: [{path: '',name: 'admin-dashboard',component: () => import('@/views/admin/DashboardView.vue'),meta: { title: '控制台' }},{path: 'users',name: 'admin-users',component: () => import('@/views/admin/UsersView.vue'),meta: { title: '用户管理' }}]},{path: '/:pathMatch(.*)*',name: 'not-found',component: () => import('@/views/NotFoundView.vue'),meta: {title: '页面不存在'}}
]const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes,scrollBehavior(to, from, savedPosition) {if (savedPosition) return savedPositionif (to.hash) return { el: to.hash, behavior: 'smooth' }return { top: 0 }}
})// 进度条配置
NProgress.configure({ showSpinner: false })// 全局前置守卫
router.beforeEach(async (to, from, next) => {NProgress.start()const authStore = useAuthStore()const isAuthenticated = authStore.isAuthenticatedconst userRole = authStore.user?.role || 'guest'// 设置页面标题document.title = to.meta.title ? `${to.meta.title} | 我的应用` : '我的应用'// 检查认证if (to.meta.requiresAuth && !isAuthenticated) {return next({name: 'login',query: { redirect: to.fullPath }})}// 检查角色权限if (to.meta.roles && !to.meta.roles.includes(userRole)) {return next({ name: 'forbidden' })}// 已登录用户访问guestOnly路由if (to.meta.guestOnly && isAuthenticated) {return next({ name: 'home' })}next()
})// 全局后置钩子
router.afterEach(() => {NProgress.done()
})export default router

2. 路由工具函数

// utils/router.js
export function resetRouter() {const newRouter = createRouter()router.matcher = newRouter.matcher // 重置路由
}export function loadRoutesByRole(role) {const dynamicRoutes = []if (role === 'admin') {dynamicRoutes.push({path: '/admin',component: () => import('@/views/AdminView.vue'),children: [// 管理员专属路由]})}dynamicRoutes.forEach(route => {router.addRoute(route)})
}export function getRouteTitle(route) {return route.meta.title || ''
}

3. 路由与状态管理集成

// stores/app.js
import { defineStore } from 'pinia'
import { useRouter } from 'vue-router'export const useAppStore = defineStore('app', {state: () => ({cachedViews: [],visitedViews: []}),actions: {addCachedView(view) {if (this.cachedViews.includes(view.name)) returnif (view.meta?.cache) {this.cachedViews.push(view.name)}},addVisitedView(view) {const existing = this.visitedViews.find(v => v.path === view.path)if (existing) {if (existing.fullPath !== view.fullPath) {// 更新现有记录Object.assign(existing, view)}return}this.visitedViews.push(Object.assign({}, view, {title: view.meta?.title || '未知'}))},async logout() {const router = useRouter()// 清理状态this.$reset()// 重定向到登录页await router.push('/login')}}
})

通过本指南,您已经全面掌握了Vue Router的核心概念和高级用法。从基础配置到导航守卫,从动态路由到状态集成,这些知识将帮助您构建复杂且高效的单页应用程序。实际项目中应根据具体需求选择合适的路由方案,并遵循最佳实践以确保应用的性能和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/906181.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前后端分离微服务架构

前后端分离微服务架构 介绍: 前端通过Vue和ElementUI构建界面&#xff0c;使用axios调用后端API。Nginx作为反向代理&#xff0c;将请求路由到Zuul网关。Zuul进行权限验证&#xff08;JWT&#xff09;后&#xff0c;将请求分发到微服务。(身份验证,安全防护(sql注入,xxs跨网站…

iOS 工厂模式

iOS 工厂模式 文章目录 iOS 工厂模式前言工厂模式简单工厂案例场景分析苹果类优点缺点 小结 工厂模式客户端调用**优点****缺点** 抽象工厂模式三个模式对比 前言 笔者之前学习了有关于设计模式的六大原则,之前简单了解过这个工厂模式,今天主要是重新学习一下这个模式,正式系统…

【机器学习】工具入门:飞牛启动Dify Ollama Deepseek

很久没有更新文章了,最近正好需要研究一些机器学习的东西&#xff0c;打算研究一下 difyOllama 以下是基于FN 的dify本地化部署&#xff0c;当然这也可能是全网唯一的飞牛部署dify手册 部署 官方手册&#xff1a;https://docs.dify.ai/en/getting-started/install-self-hos…

安卓A15系统实现修改锁屏界面默认壁纸功能

最近遇到一个A15系统项目&#xff0c;客户要求修改锁屏界面的默认壁纸&#xff0c;客户提供了一张壁纸图片&#xff0c;但是从A15系统的源代码查看时才知道谷歌已经去掉了相关的代码&#xff0c;已经不支持了&#xff0c;A13和A14系统好像是支持的&#xff0c;A15系统的Wallpap…

从理论到实战:模糊逻辑算法的深度解析与应用实践

从理论到实战&#xff1a;模糊逻辑算法的深度解析与应用实践 一、模糊逻辑的核心概念与数学基础 模糊逻辑&#xff08;Fuzzy Logic&#xff09;是一种处理不确定性的数学工具&#xff0c;其核心思想是将传统布尔逻辑的“非黑即白”扩展为连续的隶属度函数。例如&#xff0c;在…

正向代理与反向代理区别及应用

正向代理和反向代理是两种常见的代理服务器类型&#xff0c;它们在网络架构中扮演不同角色&#xff0c;核心区别在于代理对象和使用场景。 1. 正向代理&#xff08;Forward Proxy&#xff09; 定义&#xff1a;正向代理是客户端&#xff08;如浏览器&#xff09;主动配置的代理…

OpenCV CUDA模块中逐元素操作------逻辑运算

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 比较、AND、OR、NOT等。这类操作可用于创建基于条件的掩码&#xff0c;这对于图像分割或特征选择非常有用。 主要函数 1. 按位与 (cv::cuda::b…

一台入网的电脑有6要素, 机器名,mac,ip,俺码,网关,dns,分别有什么作用

一台入网的电脑需要配置的 六大网络要素&#xff08;机器名、MAC地址、IP地址、子网掩码、网关、DNS&#xff09;各自承担不同的关键作用&#xff0c;共同确保设备能正确通信和访问网络资源。以下是它们的详细功能解析&#xff1a; 1. 机器名&#xff08;主机名&#xff09; 作…

MySQL之储存引擎和视图

一、储存引擎 基本介绍&#xff1a; 1、MySQL的表类型由储存引擎(Storage Engines)决定&#xff0c;主要包括MyISAM、innoDB、Memory等。 2、MySQL数据表主要支持六种类型&#xff0c;分别是&#xff1a;CSV、Memory、ARCHIVE、MRG_MYISAN、MYISAM、InnoBDB。 3、这六种又分…

【Spring Boot后端组件】mybatis-plus使用

文章目录 mybatis-plus使用一、依赖引入二、添加相关配置项三、功能详解1.自增主键2.逻辑删除3.操作时间自动填充4.其他字段自动填充5.分页查询6.自定义动态查询7.代码生成器8.代码生成器(自定义模板) mybatis-plus使用 一、依赖引入 pom.xml文件 <?xml version"1.…

docker compose 启动指定的 service

使用 Docker Compose 启动指定服务 要在 Docker Compose 中启动特定的服务而不是所有服务&#xff0c;可以使用以下命令&#xff1a; docker compose up [服务名] 基本用法 启动单个服务&#xff1a; docker compose up service_name 启动多个指定服务&#xff1a; docker …

wordcount程序

### 在 IntelliJ IDEA 中编写和运行 Spark WordCount 程序 要使用 IntelliJ IDEA 编写并运行 Spark 的 WordCount 程序&#xff0c;需按照以下流程逐步完成环境配置、代码编写以及任务提交。 --- #### 1. **安装与配置 IntelliJ IDEA** 确保已正确安装 IntelliJ IDEA&#x…

SmartETL函数式组件的设计与应用

SmartETL框架主要采用了面向对象的设计思想&#xff0c;将ETL过程中的处理逻辑抽象为Loader和Processor&#xff08;对应loader模块和iterator模块&#xff09;&#xff0c;所有流程组件需要继承或实现DataProvider&#xff08;iter方法&#xff09;或JsonIterator&#xff08;…

鸿蒙AI开发:10-多模态大模型与原子化服务的集成

鸿蒙AI开发&#xff1a;10-多模态大模型与原子化服务的集成 在鸿蒙生态中&#xff0c;多模态大模型与原子化服务的集成是一个重要课题。本文将介绍如何在鸿蒙平台上进行多模态大模型与原子化服务的集成&#xff0c;以及相关的技术细节和实际案例。 鸿蒙AI开发概述 什么是鸿蒙AI…

python打卡day29@浙大疏锦行

知识点回顾 类的装饰器装饰器思想的进一步理解&#xff1a;外部修改、动态类方法的定义&#xff1a;内部定义和外部定义 作业&#xff1a;复习类和函数的知识点&#xff0c;写下自己过去29天的学习心得&#xff0c;如对函数和类的理解&#xff0c;对python这门工具的理解等&…

20250516使用TF卡将NanoPi NEO core开发板出厂的Ubuntu core22.04.3系统降级到Ubuntu core16.04.2

20250516使用TF卡将NanoPi NEO core开发板出厂的Ubuntu core22.04.3系统降级到Ubuntu core16.04.2 2025/5/16 10:58 缘起&#xff1a;NanoPi NEO core核心板出厂预制的OS操作系统为Ubuntu core22.04.3系统。 【虽然是友善之臂提供的最新的系统&#xff0c;但是缺少很多用用程序…

密西根大学新作——LightEMMA:自动驾驶中轻量级端到端多模态模型

导读 目前将自动驾驶与视觉语言模型&#xff08;VLMs&#xff09;结合的研究越来越火热&#xff0c;VLMs已经证明了其对自动驾驶的重要作用。本文引入了一种用于自动驾驶的轻量级端到端多模态模型LightEMMA&#xff0c;它能够集成和评估当前的商业和开源模型&#xff0c;以研究…

框架之下再看HTTP请求对接后端method

在当今的软件开发领域&#xff0c;各类框架涌现&#xff0c;极大地提升了开发效率。以 Java 开发为例&#xff0c;Spring 框架不断演进&#xff0c;Spring Boot 更是简化到只需引入 Maven 包&#xff0c;添加诸如SpringBootApplication、RestController等注解&#xff0c;就能轻…

Vue+Go 自定义打字素材的打字网站

Typing_Key_Board 这是一个基于Vue 3和Go语言的自定义素材打字练习网站&#xff0c;灵感来源于常用字打字练习&#xff0c;解决了大多数网站无法自定义打字素材的问题。在 Typing_Key_Board (简称TKB)中&#xff0c;用户可以自定义打字素材进行练习&#xff0c;在复习代码的同…

开源物联网平台(OpenRemote)

在物联网技术蓬勃发展的当下&#xff0c;OpenRemote作为一款强大的开源物联网平台&#xff0c;正逐渐在多个领域崭露头角。尤其是在智能能源管理领域&#xff0c;它为微电网和分布式能源网络提供了全面且灵活的数据集成与管理方案&#xff0c;展现出独特的优势。 OpenRemote提供…