2020-08-08-vue-router

217 阅读4分钟

说一下vue-router的原理是什么?

mode 参数:
  • 默认hash
  • history 注:如果浏览器不支持history新特性,则采用hash方式
  • 如果不在浏览器环境则使用abstract(node环境下)
HashHistory

HashHistory真是身怀绝技,会很多东西。特别是替换路由特别厉害。还可以通过不同的方式,一个是 push ,一个是 replace .

两个方法:HashHistory.push() 和 HashHistory.replace()

HashHistory.push() **将新路由添加到浏览器访问历史的栈顶 解析过程

1 $router.push() //调用方法
2 HashHistory.push() //根据hash模式调用,设置hash并添加到浏览器历史记录(添加到栈顶)(window.location.hash= XXX)
3 History.transitionTo() //监测更新,更新则调用History.updateRoute()
4 History.updateRoute() //更新路由
5 {app._route= route} //替换当前app路由
6 vm.render() //更新视图
HashHistory.replace()

replace()方法与push()方法不同之处在于,它并不是将新路由添加到浏览器访问历史的栈顶,而是替换掉当前的路由

HTML5History

History interface是浏览器历史记录栈提供的接口,通过back(), forward(), go()等方法,我们可以读取浏览器历史记录栈的信息,进行各种跳转操作。

从HTML5开始,History interface有进一步修炼:pushState(), replaceState() 这下不仅是读取了,还可以对浏览器历史记录栈进行修改:

window.history.pushState(stateObject, title, URL);
window.history.replaceState(stateObject, title, URL);
  • stateObject: 当浏览器跳转到新的状态时,将触发popState事件,该事件将携带这个stateObject参数的副本

  • title: 所添加记录的标题

  • URL: 所添加记录的URL

  • 1.push

与hash模式类似,只是将window.hash改为history.pushState

  • 2.replace

与hash模式类似,只是将window.replace改为history.replaceState

  • 3.监听地址变化

在HTML5History的构造函数中监听popState(window.onpopstate)

总结
  • pushState设置的新URL可以是与当前URL同源的任意URL;而hash只可修改#后面的部分,故只可设置与当前同文档的URL

  • pushState通过stateObject可以添加任意类型的数据到记录中;而hash只可添加短字符串

  • pushState可额外设置title属性供后续使用

  • history模式则会将URL修改得就和正常请求后端的URL一样,如后端没有配置对应/user/id的路由处理,则会返回404错误

通常情况下,我们会选择使用History模式,原因就是Hash模式下URL带着‘#’会显得不美观;但实际上,这样选择一不小心也会出问题;比如:

但当用户直接在用户栏输入地址并带有参数时:

Hash模式:xxx.com/#/id=5 请求地址为 xxx.com,没有问题;

History模式: xxx.com/id=5 请求地址为 xxx.com/id=5,如果后端没有对应的路由处理,就会返回404错误;

为解决这一问题,vue-router提供的方法是:

在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

给个警告,因为这么做以后,你的服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,你应该在 Vue 应用里面覆盖所有的路由情况,然后在给出一个 404 页面。或者,如果你使用 Node.js 服务器,你可以用服务端路由匹配到来的 URL,并在没有匹配到路由的时候返回 404,以实现回退。

珠峰答案

实现原理:vue-router的原理就是更新视图而不重新请求页面

vue-router可以通过mode参数设置为三种模式:hash模式、history模式、abstract模式。

  • 1.hash模式 默认是hash模式,基于浏览器history api,使用window.addEventListener('hashchange',callback,false)对浏览器地址进行监听。当调用push时,把新路由添加到浏览器访问历史的栈顶。使用replace时,把浏览器访问历史的栈顶路由替换成新路由 hash的值等于url中#及其以后的内容。浏览器是根据hash值的变化,将页面加载到相应的DOM位置。锚点变化只是浏览器的行为,每次锚点变化后依然会在浏览器中留下一条历史记录,可以通过浏览器的后退按钮回到上一个位置

  • 2.History history模式,基于浏览器history api ,使用window.onpopstate对浏览器地址进行监听。对浏览器history api中的pushState()、replaceState()进行封装,当方法调用,会对浏览器的历史栈进行修改。从而实现URL的跳转而无需加载页面 但是他的问题在于当刷新页面的时候会走后端路由,所以需要服务端的辅助来兜底,避免URL无法匹配到资源时能返回页面

  • 3.abstract 不涉及和浏览器地址的相关记录。流程跟hash模式一样,通过数组维护模拟浏览器的历史记录栈 服务端下使用。使用一个不依赖于浏览器的浏览器历史虚拟管理后台

  • 4.总结 hash模式和history模式都是通过window.addEvevtListenter()方法监听 hashchange和popState进行相应路由的操作。可以通过back、foward、go等方法访问浏览器的历史记录栈,进行各种跳转。而abstract模式是自己维护一个模拟的浏览器历史记录栈的数组