hash

url 上的 hash 本意是用来作锚点的,方便用户在一个很长的文档里进行上下的导航,用来做 SPA 的路由控制并非它的本意。然而,hash 满足这么一种特性:改变 url 的同时,不刷新页面,再加上浏览器也提供 onhashchange 这样的事件监听,因此,hash 能用来做路由控制。 hash方法是在路由中带有一个 #,主要原理是通过监听 # 后的 URL 路径标识符的更改而触发的浏览器 hashchange 事件,然后通过获取 location.hash 得到当前的路径标识符,再进行一些路由跳转的操作,

相关api

  1. location.href:返回完整的 URL
  2. location.hash:返回 URL 的锚部分
  3. location.pathname:返回 URL 路径名
  4. hashchange 事件:当 location.hash 发生改变时,将触发这个事件

html


js

//兼容性好(兼容到 ie8) 绝大多数前端框架均提供了给予 hash 的路由实现
//不需要服务器端进行任何设置和开发 除了资源加载和 ajax 请求以外,不会发起其他请求

// 页面加载完不会触发 hashchange,这里主动触发一次 hashchange 事件
window.addEventListener(‘DOMContentLoaded’, onLoad)
// 监听路由变化
window.addEventListener(‘hashchange’, onHashChange)

  1. // 路由视图<br /> var routerView = null
  2. function onLoad () {<br /> routerView = document.querySelector('#routeView')<br /> onHashChange()<br /> }
  3. // 路由变化时,根据路由渲染对应 UI<br /> function onHashChange () {<br /> console.log('location.hash',location.hash)<br /> switch (location.hash) {<br /> case '#/home':<br /> routerView.innerHTML = 'Home'<br /> return<br /> case '#/about':<br /> routerView.innerHTML = 'About'<br /> return<br /> default:<br /> return<br /> }<br /> }<br />![hash.png](https://cdn.nlark.com/yuque/0/2020/png/403483/1579156612072-542d7d2d-6adc-4018-ae69-f31f1585c956.png#align=left&display=inline&height=800&name=hash.png&originHeight=800&originWidth=571&size=21714&status=done&style=none&width=571)

history

  • history 提供了 pushState 和 replaceState 两个方法,这两个方法改变 URL 的 path 部分不会引起页面刷新
  • history 提供类似 hashchange 事件的 popstate 事件,但 popstate 事件有些不同:通过浏览器前进后退改变 URL 时会触发 popstate 事件,通过pushState/replaceState或<a>标签改变 URL 不会触发 popstate 事件。好在我们可以拦截 pushState/replaceState的调用和<a>标签的点击事件来检测 URL 变化,所以监听 URL 变化可以实现,只是没有 hashchange 那么方便。

相关api

history.go(-1); // 后退一页
history.go(2); // 前进两页
history.forward(); // 前进一页
history.back(); // 后退一页

history.pushState(); // 添加新的状态到历史状态栈
history.replaceState(); // 用新的状态代替当前状态
history.state // 返回当前状态对象

html

js
// 页面加载完不会触发 hashchange,这里主动触发一次 hashchange 事件
window.addEventListener(‘DOMContentLoaded’, onLoad)
// 监听路由变化
window.addEventListener(‘popstate’, onPopState)

  1. // 路由视图<br /> var routerView = null
  2. function onLoad () {<br /> routerView = document.querySelector('#routeView')<br /> onPopState()
  3. // 拦截 <a> 标签点击事件默认行为, 点击时使用 pushState 修改 URL并更新手动 UI,<br /> // 从而实现点击链接更新 URL 和 UI 的效果。<br /> var linkList = document.querySelectorAll('a[href]')<br /> console.log(linkList);<br /> linkList.forEach(el => el.addEventListener('click', function (e) {<br /> e.preventDefault()<br /> console.log(window.history.url,window.location.pathname);<br /> window.history.pushState(null, '', el.getAttribute('href'))<br /> onPopState()<br /> }))<br /> }
  4. // 路由变化时,根据路由渲染对应 UI<br /> function onPopState () {<br /> console.log('location.pathname',location.pathname)<br /> switch (location.pathname) {<br /> case '/home':<br /> routerView.innerHTML = 'Home'<br /> return<br /> case '/about':<br /> routerView.innerHTML = 'About'<br /> return<br /> default:<br /> return<br /> }<br /> }<br />![history.png](https://cdn.nlark.com/yuque/0/2020/png/403483/1579156627033-72a4ccf0-d8c1-4178-8fe5-81091a65eeca.png#align=left&display=inline&height=800&name=history.png&originHeight=800&originWidth=768&size=27888&status=done&style=none&width=768)

相关链接

# hash MDN: https://developer.mozilla.org/en-US/docs/Web/API/Window/hashchange_event
# History MDN: https://developer.mozilla.org/en-US/docs/Web/API/History
# vue history后端配置: https://router.vuejs.org/zh/guide/essentials/history-mode.html
# 前端路由实现与 react-router 源码分析 : https://github.com/joeyguo/blog/issues/2