1. hash模式
早期前端路由的实现就是基于location.hash来实现,也就是锚点。本质上就是改变window.location的href属性。我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新。这也就是,单页面应用嘛。
hash模式有下面几种特性:
- URL中hash值只是客户的一种状态,也就是说当向服务器发出请求时,hash部分是不会被发送的。
- hash值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash的切换。
- 可以通过a标签,并设置href属性,当用户点击这个标签后,URL的hash值会发生改变,或者使用JavaScript来对loaction.hash进行复制,改变URL的hash值。
- 我们可以使用hashchange事件来监听hash值的变化,从而对页面进行跳转(渲染)。
2.history模式
利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)
首先,hash 本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了。其次,hash 的传参是基于 url 的,如果要传递复杂的数据,会有体积的限制,而 history 模式不仅可以在url里放参数,还可以将数据存放在一个特定的对象中。
history 模式改变 url 的方式会导致浏览器向服务器发送请求,这不是我们想看到的,我们需要在服务器端做处理:如果匹配不到任何静态资源,则应该始终返回同一个 html 页面。
history API:
- window.history.pushState(state, title, url)
// state:需要保存的数据,这个数据在触发popstate事件时,可以在event.state里获取
// title:标题,基本没用,一般传 null
// url:设定新的历史记录的 url。新的 url 与当前 url 的 origin 必须是一樣的,否则会抛出错误。url可以是绝对路径,也可以是相对路径。
//如 当前url是 https://www.baidu.com/a/,执行history.pushState(null, null, ‘./qq/’),则变成 https://www.baidu.com/a/qq/,
//执行history.pushState(null, null, ‘/qq/’),则变成 https://www.baidu.com/qq/- window.history.replaceState(state, title, url)
// 与 pushState 基本相同,但她是修改当前历史记录,而 pushState 是创建新的历史记录- window.addEventListener(“popstate”, function() {
// 监听浏览器前进后退事件,pushState 与 replaceState 方法不会触发
});- window.history.back() // 后退
- window.history.forward() // 前进
- window.history.go(1) // 前进一步,-2为后退两步,window.history.lengthk可以查看当前历史堆栈中页面的数量
hash和histoury差异:
- hash 模式下,仅hash符号之前的内容会被包含在请求中,如http://www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误。比如这个URL:http://www.abc.com/#/hello,hash的值为#/hello.它的特点在于:hash虽然出现在URL中,但不会被包括在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面。
- history模式下,前端的URL必须和实际向后端发起请求的URL一致。如htttp://www.abc.com/test/index。如果后端缺少对/test/index 的路由处理,将返回404错误。利用了HTML5 History Interface中新增的pushState()和replaceState()方法。(需要特定浏览器支持)
这两个方法应用于浏览器的历史记录栈,在当前已有的back、forward、go的基础上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的URL,但浏览器不会即向后端发送请求。
因此可以说,hash模式和histoury模式都是属于浏览器自身的特性,Vue-Router只是利用了这两个特性(通过调用浏览器提供的接口)来实现前端路由。