目前实现路由的方式有两中,vue经过参数mode来设置,默认是hash模式。html
history对应的是HTML5History对象,hash对应的是HashHistory对象,abstract对应的是AbstractHistory对象。在初始化对应的history以前,会对mode作一些校验:若浏览器不支持HTML5History方式(经过supportsPushState遍历判断),则mode设为hash,若不是在浏览器环境下运行,则mode设为abstract前端
VueRouter类中的onReady(),push()等方法只是一个代理,实际是调用的具体history对象的对应方法,在init()方法中初始化时,也是根据history对象具体的类别执行不一样操做vue
Hash(‘#’)符号的原本做用是加在URL指示网页中的位置,#自己以及它后面的字符称之为hash,经过window.location.hash属性来获取node
Hash虽然出如今url中,但不会被包括在http请求中,它是用来指导浏览器动做的,对服务端彻底无用,所以改变hash不会从新加载页面,若是是手动在url添加hash,这时能够为hash的改变添加监听事件ajax
Window.addEventListener(‘hashchange’,funcRef,false)vue-router
每一次改变hash(window.location.hash)都会在浏览器访问历史中增长一个记录后端
执行vue里的push()方法最主要的是对window的hash进行直接赋值数组
Window.location.hash = route.fullPath浏览器
$router.push() -> HashHistory.push() -> History.transitionTo() -> History.updateRoute() -> vm.render()服务器
Replace()方法与push()方法不一样之处在于,它并非将新路由添加到浏览器访问历史栈顶,而是替换掉当前的路由,背后它其实是调用window.location.replace方法将路由进行替换
VueRouter.push()和VueRouter.replace()是能够在vue组件的逻辑代码中直接调用的,除此以外在浏览器中,用户还能够手动在浏览器地址栏中输入url,所以还须要监听浏览器地址栏中路由的变化,并具备与经过代码调用的相同响应行为,在History中经过setupListeners监听hashchange实现:
Window.addEventListener(‘hashchange’,function () {}),当在浏览器地址栏直接输入路由至关于代码调用了replace()方法
History interface是浏览器历史记录栈提供的接口,back(),forward(),go()等方法,HTML5提供了pushState(),replateState()这两个方法
Window.history.pushState(stateObject,title,url)
Window.history.replateState(stateObject,title,url)
stateObject:当浏览器跳转到新的状态时,将触发popState事件,该事件将携带这个stateObject参数的副本
title:所添加记录的标题
url:所添加记录的url
这两个方法有个共同特色:当调用他们修改浏览器历史栈后,虽然当前url改变了,但浏览器不会当即发送请求该url,这就为单页应用前端路由,更新视图但不从新请求页面提供了基础
History与hash模式基本相似,只不过将对window.location.hash()直接进行赋值window.location.replate()改成调用了window.location.history.pushState()和window.location.replateState()方法,而HTML5History中添加对修改浏览器地址栏url的监听popstate是直接在构造函数中执行的
Window.addEventListeners(‘popstate’,e => {// 执行相应的功能})
HTML5History须要浏览器的支持,vue是经过supportPushState()来检查
除这两中模式外,vue-router还未非浏览器环境准备了一个abstract模式,原理是用一个数组stack模拟除浏览器历史记录栈的功能
调用history.pushState()相比直接修改hash主要有如下优点:
对于单页面应用来讲,理想的使用场景是仅仅在进入用用时加载index’.html,后续在网络操做经过ajax完成,不会根据url从新请求页面,可是若是用户直接在地址栏中输入并回车,浏览器重启从新加载等特殊状况
Hash模式仅仅改变hash部分的内容,而hash部分是不会包含在http请求中的,就是#以及后面的是不会包含在请求当中的
http://baidu.com/#user/id //如请求,只会发送http://baidu.com
因此hash模式下遇到根据url请求页面不会有问题
而history模式则将url修改的就和政策请求后端的url同样,history不带#。http://baidu.com/user/id
若是这种向后端发送请求的话,后端没有配置对应/user/id的路由处理,会返回404错误
官方推荐的解决方法是在服务端增长一个覆盖全部状况的候选资源:若是url匹配不到任何静态资源,则应该返回同一个index.html页面,这个页面就是你app依赖的页面。同时这么作之后,服务器就再也不返回404错误页面,由于对于全部路径都会返回index.html文件。为了不这种状况,在vue应用里面覆盖全部的路由状况,而后再给出一个404页面。或者若是是用node.js作后台,可使用服务端的路由来匹配url,当没有匹配到路由的时候返回404,从而实现fallback