详细介绍Vue-Router及其实现原理、路由模式
1、Vue-Router 是什么?
Vue Router 是 Vue.js 官方提供的前端路由管理库,用于构建单页应用(SPA, Single Page Application)时,实现页面之间的导航切换。
Vue Router 的作用:
功能 | 说明 |
---|---|
页面导航 | 支持 <router-link> 标签点击跳转 |
动态路由 | 支持参数,如 /user/:id |
嵌套路由 | 支持组件嵌套页面结构 |
路由守卫 | 支持进入/离开前的权限判断、跳转控制 |
编程式导航 | 通过 JS 控制跳转 router.push() 等 |
历史记录管理 | 支持 history 或 hash 模式切换 |
2、Vue-Router 实现原理
核心原理是 更新视图但不重新请求页面。
router是伴随spa单页面应用产生的一种页面挑战实现方案,SPA(single page application):单一页面应用程序,只有一个完整的页面;它在加载页面时,不会加载整个页面,而是只更新某个指定的容器中内容。单页面应用(SPA)的核心之一是: 更新视图而不重新请求页面;
工作流程示意图:
用户点击 router-link 或执行 router.push()↓ Vue Router 监听到 URL 变化 ↓ 匹配对应的路由规则(path -> component) ↓ 把 <router-view> 替换为对应组件↓ 页面内容切换,但不刷新页面
3、Vue-Router 路由模式
vue 在实现单页面前端路由时,提供了两种方式:Hash模式和History模式;根据mode参数来决定采用哪一种方式。
作用:通过改变URL,在不重新请求页面的情况下,更新页面视图。简单的说就是,虽然地址栏的地址改变了,但是并不是一个全新的页面,而是之前的页面某些部分进行了修改。
源码分析:
先获取mode的值,如果mode的值为
history
但是浏览器不支持history
模式,那么就强制设置mode值为hash
。如果支持则为history
。接下来,根据mode的值,来选择vue-router使用哪种模式。hash 中的 push:window.location.hash = route.fullPath hash的改变会自动添加到浏览器的访问历史记录中。
history:提供了两个新的方法:pushState(), replaceState()使得我们可以对浏览器历史记录栈进行修改。当调用他们修改浏览器历史记录栈后,虽然当前URL改变了,但浏览器不会刷新页面(更新视图但不重新请求页面).
3.1、Hash模式:
- location.hash 的值实际就是 URL 中#后面的东西 ,原理: hash 模式的主要原理就是onhashchange()事件
- 它的特点在于:hash 虽然出现 URL 中,但不会被包含在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
- 可以为 hash 的改变添加监听事件
window.addEventListener("hashchange", funcRef, false);
每一次改变 hash(window.location.hash),都会在浏览器的访问历史中增加一个记录利用 hash 的以上特点,就可以来实现前端路由“更新视图但不重新请求页面”的功能了
优点:由于发送https请求时不会带上hash值,因此无论是刷新页面或者改变hash值都不会影响到服务器端。
缺点:
- 当使用hash值做路由时,锚点功能就失效了
- hash方式传递参数的限制是基于浏览器url最大参数限制的。
- hash方式导致浏览器地址栏出现#不美观
3.2、History模式:
vue-router中history模式的部分实现使用了html5新增的pushState()和replaceState(),这两个方法均来自于浏览器的历史记录栈,它的作用是添加或者替换浏览器历史记录中的条目。
通过这两个 API (1)可以改变 url 地址且不会发送请求,(2)不仅可以读取历史记录栈,还可以对浏览器历史记录栈进行修改。
window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
包括forward、back、go三个方法,对应浏览器的前进,后退,跳转操作。就是浏览器左上角的前进、后退等按钮进行的操作。
- history.go(-2);//后退两次
- history.go(2);//前进两次
- history.back(); //后退
- hsitory.forward(); //前进
优点:
- 很方便的获取到传递的参数。并且能传递最大640kb的对象
- 后端也能很方便的获取到路由的地址
缺点:
- 刷新页面,如果没有相应的路由或资源,可能会导致页面404,前端url必须与发送到服务器请求的url相同
- 改变url地址后,会重新请求服务器。
3.3、Vue-Router 的内部监听机制
Vue Router 会根据模式自动设置相应的监听器:
1、基于 Hash Mode
// 监听hashchange事件
window.addEventListener('hashchange', () => {// URL的hash部分发生变化,更新路由状态
});
2、基于 History API
// Vue Router 内部使用 History API
window.history.pushState(state, title, url) // 添加新历史记录
window.history.replaceState(state, title, url) // 替换当前历史记录// 监听popstate事件(浏览器前进/后退)
window.addEventListener('popstate', () => {// URL发生变化,更新路由状态
});
常见问题:
Vue-Router怎么知道哪个URL发生变化的URL变化时候会触发哪些事件?
简答:
Vue Router 通过:
- 监听浏览器事件(popstate/hashchange)
- 重写导航方法(push/replace)
- 维护内部状态机来跟踪路由变化
// 伪代码:Vue Router 内部的监听逻辑 if (mode === 'history') {window.addEventListener('popstate', handleRouting);// 重写pushState/replaceState来触发更新 } else {window.addEventListener('hashchange', handleRouting); }
详细:
Vue-Router 本质上是通过监听浏览器提供的 原生事件 来感知URL变化的。根据运行环境(浏览器或Node.js)和模式(Hash 或 History),其监听方式略有不同。
Vue-Router 通过监听以下浏览器事件来捕获URL变化:
1、对于 Hash 模式 (
mode: 'hash'
):
hashchange
事件:这是最主要的监听方式。当URL的hash部分(即#
及后面的内容)发生变化时,浏览器会自动触发window
上的hashchange
事件。Vue-Router 会监听这个事件来更新其内部状态和匹配对应的路由。2、对于 History 模式 (
mode: 'history'
):
popstate
事件:当用户点击浏览器的前进/后退按钮,或者通过history.back()
,history.forward()
,history.go()
方法进行导航时,会触发window
上的popstate
事件。Vue-Router 监听这个事件来响应由浏览器行为引发的路由变化。手动拦截:对于程序触发的导航(如通过
<router-link>
点击或调用router.push()
/router.replace()
),Vue-Router 不需要通过事件监听。它直接在调用这些方法时,内部会同步地更新状态、匹配路由,并最终调用history.pushState()
或history.replaceState()
来改变URL而不会触发popstate
事件。
完整的事件/钩子触发顺序图表:
3.4、使用场景
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
当然啦,history 也不是样样都好。SPA 虽然在浏览器里游刃有余,但真要通过 URL 向后端发起 HTTP 请求时,两者的差异就来了。尤其在用户手动输入 URL 后回车,或者刷新(重启)浏览器的时候。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
history 模式下,不怕前进,不怕后退,就怕刷新,(如果后端没有准备的话),因为刷新是实实在在地去请求服务器的。前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.abc.com/book/id。如果后端缺少对 /book/id 的路由处理,将返回 404 错误。
特殊:
Abstract 模式是 Vue Router 提供的三种路由模式之一,主要用于非浏览器环境,例如服务器端渲染(SSR)或其他不支持浏览器 API 的场景。abstract 是vue路由中的第三种模式,本身是用来在不支持浏览器API的环境中,充当fallback,而不论是hash还是history模式都会对浏览器上的url产生作用,本文要实现的功能就是在已存在的路由页面中内嵌其他的路由页面,而保持在浏览器当中依旧显示当前页面的路由path,这就利用到了abstract这种与浏览器分离的路由模式。它不会针对 URL 进行任何的修改,只是通过内存中的路由表来进行路由跳转。