一、vue-router的实现原理
首先vue-router实现了 在无需刷新页面的情况下更新视图
对比:location.href=""实现了跳转但是刷新了页面
在浏览器环境下的两种方式,分别就是在HTML5History,HashHistory两个类中实现的。
两个模式hash和history
1.hash模式,主要是hashHistory
原理:
- hash(“#”)符号的本来作用是加在URL中指示网页中的位置
- hash虽然出现在URL中,但不会被包括在HTTP请求中。它是用来指导浏览器动作的,对服务器端完全无用,因此,改变hash不会重新加载页面
- 每一次改变hash(window.location.hash),都会在浏览器的访问历史中增加一个记录
- 改变hash可以监听到hashchange事件
window.addEventListener("hashchange", funcRef, false)
底层处理路由更新(push)的流程:
- push方法 对window的hash直接赋值
window.location.hash = route.fullPath
- router是怎么做到在每一个Vue组件中都能使用的呢?
- 在插件加载的地方,即VueRouter的install方法中通过Vue.mixin()全局注册一个混合,影响到每一个组件。
- Vue.mixin()做了什么?
export function install (Vue) {
Vue.mixin({
beforeCreate () {
if (isDef(this.$options.router)) {
this._router = this.$options.router
this._router.init(this)
Vue.util.defineReactive(this, '_route', this._router.history.current)
}
registerInstance(this, this)
},
})
}
- 看代码我们知道Vue.mixin()在beforeCreate钩子中通过Vue.util.defineReactive()定义了响应式的route属性,所谓响应式其实就是,当route值改变时,调用Vue的render方法,更新视图
2.history模式,主要利用HTML5History
- 我们主要利用这个HTML5History来操作浏览器历史记录栈,
- 主要方法有back(), forward(), go()来读取浏览器路由历史并控制跳转
- HTML5新增pushState(), replaceState()2个方法来修改历史信息,调用这两个方法修改历史信息后,虽然当前URL改变了,但浏览器不会立即发送请求该URL,这就满足单页面应用”更新视图但不重新请求页面“的需求
- 修改浏览器历史记录后会触发popstate事件,我们可以通过监听popstate事件
3.两种模式的比较,history模式更有优势
- hash模式有#,history模式没有#,更美观
- pushState设置的新url是和当前url同源的任意url,hash模式只可以修改#后面的内容,也就是只可以设置与当前同文档的url
- pushState设置的新url和当前url相同时也会把记录添加进记录栈中,而hash只有新的和当前的不同的时候才会添加到栈中
4.关于这两种模式的实战问题
移动端采用WebView加载Vue单页应用时,要采用hash模式
解释:
- 因为我们默认第一页是https://....../html
- 如果是history模式,他要匹配/,就匹配不到,就会报错
- 如果是hash模式,会强行加入#/,然后再匹配#/,就能匹配到
5.再来一个实战问题
我们理想的情况是通过index.html进入页面,后续的操作都由ajax完成,但是如果遇到用户直接在地址栏中输入然后回车或者强行重新加载等操作
history模式下:
http://oursite.com/user/id
hash模式下:
http://oursite.com/#/user/id
通过上面例子,我们可以知道history模式会像服务器发起请求,这时如果服务端没有匹配的路由处理,则报错;如果请求了某一个接口的数据,则有可能显示返回值json串。
解决方案:
a. 前端设置一个通用路由重定向到html页
b. 后端在接收到没有配置的请求的时候返回401或别的状态码
c. 使用token