在单页应用中,一般由前端来配置路由,根据不一样的 url 显示不一样的内容。想要知道这是如何作到的,首先得了解浏览器提供的两大 API:前端
window.location
vue
location.href
location.hash
location.search
location.pathname
window.history
vue-router
history.pushState()
history.replaceState()
history.go()
history.back()
history.forward()
咱们先了解 location 对象,location 有不少的属性。咱们能够经过改变其属性值修改页面的 url。咱们在单页应用中须要作到的是改变 url 不刷新页面,location 接口提供如下两种方式能够作到:后端
location.href
赋值时只改变 url 的 hashlocation.hash
而上面的列出其他两个属性 location.search
会直接刷新页面,这个就不解释了。但 location.pathname
照道理来讲只改变 hash 应该是能够的,但实际上浏览器会编码这个属性值,因此没法直接赋带 # 号的值。浏览器
history 接口是 HTML5 新增的,它有五个方法能够改变 url 而不刷新页面。编码
history.pushState()
history.replaceState()
history.go()
上面只演示了三个方法,由于 history.back()
等价于 history.go(-1)
,history.forward()
则等价于 history.go(1)
,这三个接口等同于浏览器界面的前进后退。url
如今咱们已经知道如何不刷新页面改变页面的 url。虽然页面没刷新,但咱们要改变页面显示的内容。这就须要 js 监听 url 的变化从而达到咱们的目的。spa
咱们有两个事件能够监听 url 的改变:code
hashchange
事件能监听 url hash 的改变。router
先要加上事件监听的代码:
window.addEventListener('hashchange', function(e) { console.log(e) })
而后就能够在页面的 console 里愉快的实验了:
从上图中咱们能够知道无论是经过 location 接口直接改变 hash,仍是经过 history 接口前进后退(只是 hash 改变的状况下),咱们均可以监听到 url hash 的改变。但这个事件也只能监听 url hash 的变化。因此咱们须要一个更强大的事件:popstate
。
popstate 事件能监听除 history.pushState()
和 history.replaceState()
外 url 的变化。
先加上事件监听的代码:
window.addEventListener('popstate', function(e) { console.log(e) })
而后又能够在页面的 console 里愉快的实验了:
其实不止 history.pushState()
和 history.replaceState()
对 url 的改变不会触发 popstate
事件,当这两个方法只改变 url hash 时也不会触发 hashchange
事件。
咱们都知道单页应用的路由有两种模式:hash 和 history。若是咱们在 hash 模式时不使用 history.pushState()
和 history.replaceState()
方法,咱们就只须要在 hashchange
事件回调里编写 url 改变时的逻辑就好了。而 history 模式下,咱们不只要在 popstate
事件回调里处理 url 的变化,还须要分别在 history.pushState()
和 history.replaceState()
方法里处理 url 的变化。并且 history 模式还须要后端的配合,否则用户刷新页面就只有 404 能够看了?
因此 hash 模式下咱们的工做实际上是更简单的,但为何如今都推荐用 history 模式呢?总不是 hash 模式下的 url 太丑了,毕竟这是个看脸的世界?
不过 vue-router
在浏览器支持 pushState()
时就算是 hash 模式下也是用 history.pushState()
来改变 url,不知道有没什么深意?还有待研究...