实现原理:vue-router 的原理就是更新视图而不重新请求页面
vue-router 可以通过 mode 参数设置为三种模式:hash 模式、history 模式、abstract 模式。
- hash 模式。默认是 hash 模式,基于浏览器 history api,使用 window.addEventListener("hashchange", callback, false) 对浏览进行监听。当调用 push 时,把新路由添加到浏览器访问历史的栈顶。使用 replace 时,把浏览器访问历史的栈顶路由替换成新路由 hash 的值(等于 url 中 # 及其以后的内容)。浏览器是根据 hash 值的变化,将页面加载到相应的 DOM 位置。锚点变化只是浏览器的行为,每次锚点变化后依然会在浏览器中留下一条历史记录,可以通过浏览器的后退按钮回到上一个位置。
- history 模式。基于浏览器 history api,使用 window.onpopstate 对浏览器地址进行监听。对浏览器 history api 中的 pushState()、replaceState() 进行封装,当方法调用,会对浏览器的历史栈进行修改。从而实现 URL 的跳转而无需加载页面,但是它的问题在于当刷新页面的时候会走后端路由,所以需要服务端的辅助来完成,避免 url 无法匹配到资源时能返回页面。
- abstract 。不涉及和浏览器地址的相关记录。流程跟 hash 模式一样,通过数组维护模拟浏览器的历史记录栈 服务端下使用。使用一个不依赖于浏览器的浏览器历史虚拟管理后台
总结:
hash 模式和 history 模式都是通过 window.addEventListener() 方法监听 hashchange 和 popState 进行相应路由的操作。可以通过 back、foward、go 等方法访问浏览器的历史记录栈 进行各种跳转。而 abstract 模式是自己维护一个模拟的浏览器历史记录栈的数组。
通常情况下,我们会选择 history 模式,原因就是 hash 模式下 url 带 # 会显得不美观;但实际上,这样选择一不小心也会出问题;比如:
当用户直接在用户栏输入地址并带有参数时:
hash 模式:xxx.com/#/id=5 请求地址为 xxx.com,没有问题;
history 模式:xxx.com/id=5 请求地址为 xxx.com/id=5,如果后端没有对应的路由处理,就会返回 404错误;
为解决 history 模式的 404 问题,vue-router 提供的方法是:
在服务端增加一个覆盖所有情况的候选资源:如果 url 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是 app 依赖的页面。
给个警告,因为这么做以后,你的服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,你应该在 vue 应用里面覆盖所有的路由情况,然后再给出一个 404 页面。或者,如果你使用 node.js 服务器,你可以用 服务端路由匹配到来的 url,并在没有匹配到路由的时候返回 404,以实现回退。