1. vue-router的原理是什么?
Vue Router 的核心是通过 路由模式监听 URL 变化 → 动态匹配组件 → 响应式更新视图,实现单页面应用的无刷新导航。选择 Hash 或 History 模式需根据项目需求权衡美观性、兼容性和服务器支持。对于复杂场景,可结合导航守卫、懒加载等特性优化用户体验
路由模式的核心实现
Vue Router 支持三种路由模式,其底层机制如下:
- Hash 模式(默认模式)
- 原理:利用 URL 中的
#符号(哈希值)作为路由标识。哈希值的变化不会触发浏览器向服务器发送请求。 - 实现方式:
-
- 通过
window.addEventListener('hashchange', callback)监听哈希变化。 - 哈希值变化时,解析路径并匹配对应组件,通过
<router-view>动态渲染。
- 通过
- 优点:兼容性好(支持所有浏览器),无需服务器配置。
- 缺点:URL 中带有
#,不够美观。
- History 模式
- 原理:基于 HTML5 的
History API(pushState和replaceState),直接操作浏览器历史记录栈。 - 实现方式:
-
- 通过
history.pushState()或history.replaceState()修改 URL。 - 通过
window.addEventListener('popstate', callback)监听浏览器前进/后退操作。
- 通过
- 优点:URL 无
#,更符合传统 URL 结构。 - 缺点:需服务器配置(所有路径重定向到
index.html),否则直接访问子路径会返回 404。
- Memory 模式
- 原理:通过数组模拟浏览器历史记录栈,不依赖浏览器 API,适用于非浏览器环境(如 Node.js 或移动端)
Vue Router 的核心工作流程
- 初始化路由表
定义路由配置(routes数组),将路径与组件映射。例如:
javascript
const routes = [
{ path: '/user/:id', component: User }, // 动态路由
{ path: '/parent', component: Parent, children: [...] } // 嵌套路由
];
- 监听 URL 变化
-
- Hash 模式监听
hashchange事件,History 模式监听popstate事件。
- Hash 模式监听
- 动态匹配路由
-
- 根据当前 URL 解析路径参数(如
/user/123中的id=123),匹配路由表中对应的组件。
- 根据当前 URL 解析路径参数(如
- 组件渲染
-
- 通过
<router-view>组件作为占位符,动态渲染匹配到的组件。
- 通过
- 状态更新
-
- 使用响应式变量(如
current)跟踪当前路由状态,触发视图更新。
- 使用响应式变量(如
关键特性与进阶实现
1. 动态路由与嵌套路由
- 动态路由:通过冒号
:定义路径参数(如/user/:id),在组件中通过$route.params获取参数。 - 嵌套路由:通过
children配置子路由,父组件中嵌套<router-view>渲染子组件。
2. 导航守卫
- 作用:在路由跳转前后执行逻辑(如权限验证、数据预加载)。
- 类型:
-
- 全局守卫(
router.beforeEach)。 - 路由独享守卫(
beforeEnter)。 - 组件内守卫(
beforeRouteEnter、beforeRouteLeave)。
- 全局守卫(
3. 懒加载
- 实现:通过动态导入语法(
() => import('./Component.vue'))按需加载组件,提升首屏性能
Hash 模式和History 模式对比
| 对比维度 | Hash 模式 | History 模式 |
|---|---|---|
| URL 美观性 | 带有 # | 无 #,更接近传统 URL |
| 兼容性 | 支持所有浏览器 | 需浏览器支持 History API |
| 服务器配置 | 无需特殊配置 | 需配置重定向(如 Nginx 的 try_files) |
| 适用场景 | 简单项目、兼容性要求高 | 需 SEO 优化、URL 美观的正式项目 |
2. 路由守卫的执行顺序是什么?
2.1. 完整执行顺序(从路由 A 跳转到路由 B)
- 组件内离开守卫:
beforeRouteLeave
-
- 触发时机:导航离开当前组件时(如从 A 组件跳转至 B 组件)。
- 作用:处理离开前的操作(如保存未提交数据)。
- 注意:可访问当前组件实例
this。
- 全局前置守卫:
beforeEach
-
- 触发时机:所有路由跳转的入口拦截。
- 作用:全局权限验证(如登录状态检查)。
- 路由独享守卫:
beforeEnter
-
- 触发时机:仅针对目标路由(如 B 路由)的拦截。
- 作用:特定路由的权限控制(如管理员访问限制)。
- 组件内复用守卫:
beforeRouteUpdate
-
- 触发时机:仅当组件复用时触发(如动态路由参数变化,如
/user/1→/user/2)。 - 作用:更新组件内数据(如重新获取用户详情)。
- 触发时机:仅当组件复用时触发(如动态路由参数变化,如
- 组件内进入守卫:
beforeRouteEnter
-
- 触发时机:目标组件(B 组件)渲染前。
- 作用:预加载数据(如异步请求),但无法访问 ****
this(需通过next(vm => {})回调获取实例)。
- 全局解析守卫:
beforeResolve
-
- 触发时机:所有前置守卫完成后,导航确认前。
- 作用:最终安全检查或数据准备(如确保所有异步操作完成)。
- 全局后置钩子:
afterEach
-
- 触发时机:导航完成后。
- 作用:执行与导航无关的后置操作(如埋点统计、页面标题更新)。
2.2. 二、特殊场景说明
2.2.1. 1. 组件复用时(动态路由参数变化)
- 执行顺序:
beforeRouteLeave→beforeEach→beforeRouteUpdate→beforeResolve→afterEach。 - 示例:从
/user/1跳转到/user/2,复用User组件,触发beforeRouteUpdate。
2.2.2. 2. 嵌套路由跳转
- 执行顺序:父组件的
beforeRouteLeave→ 子组件的beforeRouteLeave→ 全局beforeEach→ 子路由的beforeEnter→ 子组件的beforeRouteEnter。
2.2.3. 3. 异步组件加载
- 触发时机:在
beforeEnter和beforeRouteEnter之间解析异步组件。 - 示例:使用
() => import('./User.vue')动态导入组件时,需等待组件加载完成。
2.3. 三、核心注意事项
next()****的调用
-
- 必须显式调用
next(),否则导航会挂起。 - 控制跳转:通过
next(false)中断导航,或next('/login')重定向。
- 必须显式调用
beforeRouteEnter****的特殊性
-
- 无法访问 ****
this:因组件实例尚未创建,需通过next(vm => {})回调操作实例。 - 唯一支持回调的守卫:其他守卫可直接访问
this。
- 无法访问 ****
- 错误处理
-
- 全局错误捕获:通过
router.onError()捕获next(error)抛出的异常。
- 全局错误捕获:通过