深入理解 Vue Router_深入理解微电子电路设计
在前端单页应用(SPA)中,路由是连接用户操作与页面展示的核心桥梁。Vue Router 作为 Vue 官方的路由管理器,提供了丰富的功能和灵活的配置。本文将围绕“路由模式”、“router 与 route 的区别”、“导航守卫的种类”以及“完整的导航解析流程”四个方面,带你深入理解 Vue Router 的工作机制。
一、路由模式:hash 与 history 的实现原理
Vue Router 支持两种主流的路由模式:hash 模式 和 history 模式。它们的底层实现机制不同,决定了使用方式和部署时的差异。
1. hash 模式
hash 模式是基于 URL 中 # 后面的内容变化实现的。浏览器不会将 # 后的部分发送到服务器,因此不会触发页面刷新。
- 监听机制:通过监听 window.onhashchange 事件,捕获 hash 值的变化。
- 优点:兼容性好,支持 IE 及以下版本。部署简单,刷新页面不会 404。
- 缺点:URL 不够美观,带有 # 符号。
2. history 模式
history 模式依赖 HTML5 提供的 pushState 和 replaceState API,可以在不刷新页面的情况下修改 URL。
- 监听机制:通过监听 popstate 事件,捕获浏览器前进/后退操作。
- 优点:URL 更干净,没有 #。
- 缺点:需要后端配合,刷新页面或直接访问子路径时,需将所有请求重定向到入口文件(如 index.html),否则会返回 404。对低版本浏览器支持不佳。
二、router 与 route 的区别
在 Vue 组件中,我们常常使用 this.$router 和 this.$route,但它们代表的含义完全不同:
router
- 是 Vue Router 的实例对象,包含整个路由的配置和控制方法。
- 常用方法:this.$router.push():跳转到指定路由,添加一条历史记录。this.$router.replace():替换当前路由,不添加历史记录。this.$router.go(n):前进或后退 n 步。
route
- 是当前激活路由的信息对象,包含与当前路径相关的所有信息。
- 常用属性:this.$route.path:当前路径,如 /user/123。this.$route.params:动态路由参数,如 { id: 123 }。this.$route.query:查询参数,如 ?tab=profile 对应 { tab: 'profile' }。this.$route.name:当前路由的名称。this.$route.meta:路由元信息,常用于权限控制。
简言之:router 是“路由器”,负责操作;route 是“当前路线”,负责提供信息。
三、导航守卫的种类
Vue Router 提供了多种导航守卫,用于在路由跳转前后执行逻辑控制,分为三大类:
1. 全局守卫
作用于整个应用,定义在 router 实例上:
- router.beforeEach(to, from, next):全局前置守卫,常用于登录验证。
- router.beforeResolve(to, from, next):全局解析守卫,2.5+ 引入,所有组件内守卫和异步路由组件解析完成后触发。
- router.afterEach(to, from):全局后置钩子,不能拦截导航,常用于页面埋点。
2. 路由独享守卫
定义在单个路由配置中,仅对该路由生效:
- beforeEnter(to, from, next):进入该路由前触发,用法与全局守卫类似。
3. 组件内守卫
定义在 Vue 组件内部,与组件生命周期紧密结合:
- beforeRouteEnter(to, from, next):组件被激活前调用,此时组件实例尚未创建,无法访问 this。
- beforeRouteUpdate(to, from, next):当前路由改变但组件被复用时调用(如 /user/1 → /user/2)。
- beforeRouteLeave(to, from, next):离开当前路由时调用,可用于提示用户保存未提交的表单。
四、完整的导航解析流程
Vue Router 的导航过程是一个链式调用的过程,每一步都可以中断或继续。以下是完整的流程:
- 导航触发:用户点击 <router-link> 或调用 $router.push()。
- 调用失活组件的 beforeRouteLeave:如从 /user/1 跳转到 /about。
- 调用全局 beforeEach 守卫。
- 调用重用组件的 beforeRouteUpdate(若组件被复用)。
- 调用路由独享的 beforeEnter。
- 解析异步组件(若该路由配置了异步组件)。
- 调用激活组件的 beforeRouteEnter。
- 调用全局 beforeResolve 守卫。
- 导航被确认。
- 调用全局 afterEach 钩子。
- 触发 DOM 更新。
- 执行 beforeRouteEnter 中 next 的回调,此时组件实例已创建,可通过回调参数访问。