Vue Router的路由模式 hash 和 history 的实现原理和区别详解

4,362 阅读4分钟

vue的两种路由模式hash和history模式以及它们的底层实现原理

一.hash 模式:在浏览器中符号“#”,#以及#后面的字符称之为 hash, 用 window.location.hash 读取。特点:hash 虽然在 URL 中,但不被包括在 HTTP 请求中;用来指导浏览器动作,对服务端安全无用,hash 不会重加载页面。路由的哈希模式其实是利用了window.onhashchange事件,也就是说你的url中的哈希值(#后面的值)如果有变化,就会自动调用hashchange的监听事件,在hashchange的监听事件内可以得到改变后的url,这样能够找到对应页面进行加载

二.history 模式:history 采用 HTML5 的新特性;且提供了两个新方法: pushState(), replaceState()可以对浏览器历史记录栈进行修改,以 及 popState 事件的监听到状态变更pushState方法、replaceState方法,只能导致history对象发生变化,从而改变当前地址栏的 URL,但浏览器不会向后端发送请求,也不会触发popstate事件的执行

popstate事件的执行是在点击浏览器的前进后退按钮的时候,才会被触发

在vue的router中,通过修改vueRouter的mode属性来决定使用history还是hash。默认为hash模式。
const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})
export default router

1.hash 路由模式的实现主要是基于下面几个特点:

  • URL 中的 hash 值只是客户端的一种状态,向服务端发送请求的时候,hash 部分不会被发送。
  • hash 值得改变会在浏览器的历史记增加访问记录,所以可以通过浏览器的回退、前进控制 hash 值的改变。
  • 可以通过 a 标签设置 href 值或者通过 js 给location.hash 赋值来改变 hash 值。
  • 可以通过hashchang 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。

2.history 路由模式的实现主要是基于下面几个特点:

  • 通过 pushState 和 replaceState 两个API 来操作实现 URL 的变化。
  • 可以通过 popstate 事假来监听 URL 的变化,从而对页面进行跳转(渲染)。
  • history.pushState() 或 history.replaceState() 不会触发 popstate 事件,需要手动触发页面跳转

hash和history的区别

1.形式上:hash模式url里面永远带着#号,开发当中默认使用这个模式。如果用户考虑url的规范那么就需要使用history模式,因为history模式没有#号,是个正常的url,适合推广宣传;
2.功能上:比如我们在开发app的时候有分享页面,那么这个分享出去的页面就是用vue或是react做的,咱们把这个页面分享到第三方的app里,有的app里面url是不允许带有#号的,所以要将#号去除那么就要使用history模式,但是使用history模式还有一个问题就是,在访问二级页面的时候,做刷新操作,会出现404错误,那么就需要和后端人配合,让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上就ok了

使用场景

一般场景下,hash 和 history 都可以,除非你更在意颜值,# 符号夹杂在 URL 里看起来确实有些不太美丽。

如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成URL 跳转而无须重新加载页面。 Vue-router 另外,根据 Mozilla Develop Network 的介绍,调用 history.pushState() 相比于直接修改 hash,存在以下优势:

pushState() 设置的新 URL 可以是与当前 URL 同源的任意 URL;而 hash 只可修改 # 后面的部分,因此只能设置与当前 URL 同文档的 URL
pushState() 设置的新 URL 可以与当前 URL 一模一样,这样也会把记录添加到栈中;而 hash 设置的新值必须与原来不一样才会触发动作将记录添加到栈中
pushState() 通过 stateObject 参数可以添加任意类型的数据到记录中;而 hash 只可添加短字符串
pushState() 可额外设置 title 属性供后续使用

总结

传统的路由指的是:当用户访问一个url时,对应的服务器会接收这个请求,然后解析url中的路径,从而执行对应的处理逻辑。这样就完成了一次路由分发

而前端路由是不涉及服务器的,是前端利用hash或者HTML5的history API来实现的,一般用于不同内容的展示和切换