一、前言

对于hash模式和history模式,最直接的区别就是地址栏带不带"#"号了。
vue脚手架搭建的项目的路由默认是hash模式。
hash模式:
在这里插入图片描述
创建路由实例时,添加mode:"history"属性,即可使用history模式。

const router = new VueRouter({
  routes,
  mode: "history"
})

history模式:
在这里插入图片描述

二、hash模式

最开始学习超链接a时,就可以利用锚点”#”实现跳转到同一页面的不同id所对应的位置。我们知道vue是单页面应用,所以很符号使用锚点实现路由。

打开vue官网,点击 “vuejs是什么目录”:
可以看到地址栏,是带#的,所以是hash模式:
在这里插入图片描述
打开控制台,输入window.location(包含了浏览器地址栏的地址信息):
在这里插入图片描述

路由的哈希模式其实是利用了window.onhashchange事件,也就是哈希值(#后面的值)如果有变化,就会自动调用hashchange的监听事件,在hashchange的监听事件内可以得到改变后的url,这样能够找到对应页面进行加载。

三、history模式

使用hash模式完全可以实现路由的功能,但是,地址栏带"#号",让人感觉不太正常。而且有的时候分享页面到某些app时,有的app里面url是不允许带有#号的。所以需要使用history模式,去掉“#号”。

前面知道了hash模式是观察window.location.hash的变化来改变路由的。

而HTML5 History Interface 中新增的两个神器 pushState()replaceState() 方法(需要特定浏览器支持),用来完成 URL 跳转而无须重新加载页面。

每个window窗口都有持有自己的history,为了安全起见history不会暴露访问过的URL,但是可以通过API进行前进或后退访问URL的内容

1、 window.history.pushState(data, title, targetURL);
@状态对象:传给目标路由的信息,可为空
@页面标题:目前所有浏览器都不支持,填空字符串即可
@可选url:目标url,不会检查url是否存在,且不能跨域。如不传该项,即给当前url添加data
2、window.history.replaceState(data, title, targetURL);
@类似于pushState,但是会直接替换掉当前url,而不会在history中留下记录。
3、popstate事件,回退,与pushState作用相反。

通俗地说就是浏览器的地址栏url信息存储在了window.history.state中,但是调试时我们发现,其为null,是为了防止网页获取你的历史浏览地址,所以给隐藏了,但是其内部可以获取。

在这里插入图片描述

举一个例子,立马就明白了:
打开百度,搜索“CSDN”:

在这里插入图片描述

然后我们打开控制台,输入:

window.history.replaceState(null, 'title', 'https://www.baidu.com/')

效果:
在这里插入图片描述

地址栏变成了百度首页的地址,但是并不影响当前页面的内容。这也就是history模式下vue单页面实现不同路由显示的原理,程序中路由改变时,将路由地址显示在地址栏,然后根据路由对应的地址显示组件就行了,此时并没有重新请求服务器,但是地址栏确改变了,给用户造成了页面跳转的假象。然而,我们知道,vue项目中,我们一直都在index.html中。

但是,同时也暴露了history一个问题,就如上面的例子,如果我将地址栏替换为"https://www.baidu.com/"后,刷新页面,肯定会跳转到百度首页的,因为刷新会重新请求服务器的。然而实际应用中,vue中的路由地址并没有在服务器上有对应的后端处理,它仅仅用于前端的路由切换。

那么如何解决呢?这就需要服务器端做点手脚,将不存在的路径请求重定向到入口文件(index.html)。

所以相比于hash,history虽然可以实现正常美观的地址显示,但是代价就是需要解决刷新时请求服务器的404的问题。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐