早期的路由都是后端实现的,直接根据 url
来 reload 页面,页面变得愈来愈复杂服务器端压力变大,随着 ajax
的出现,页面实现非 reload 就能刷新数据,也给前端路由的出现奠基了基础。咱们能够经过记录 url
来记录 ajax
的变化,从而实现前端路由。前端
router
url
History
hash
react
你们能够查看MDN的文档:https://developer.mozilla.org/en-US/docs/Web/API/History
本文主要说两个新增的API history.pushState
和 history.replaceState
(相同之处: 都会操做浏览器的历史记录,而不会引发页面的刷新。
不一样之处: pushState会增长一条新的历史记录,而replaceState则会替换当前的历史记录。)ajax
这两个 API 都接收三个参数,分别是状态对象(state) — 不管什么时候用户导航到新建立的状态,popstate
事件都会被触发,而且事件对象的state
属性都包含历史记录条目的状态对象的拷贝,默认null。后端
标题(title) — 标明将要进入的状态,默认null。浏览器
地址(URL) — 新的历史记录条目的地址,传入的URL与当前URL应该是同源的,不然,pushState()会抛出异常。默认为当前URL。服务器
咱们在百度的控制台输入react-router
window.history.pushState(null, null, "https://www.baidu.com/?name=zzz")
此时url变成了这样框架
状态对象(state) — 不管什么时候用户导航到新建立的状态,popstate
事件都会被触发,而且事件对象的state
属性都包含历史记录条目的状态对象的拷贝,默认null。url
标题(title) — 标明将要进入的状态,默认null。spa
地址(URL) — 新的历史记录条目的地址,传入的URL与当前URL应该是同源的,不然,pushState()会抛出异常。默认为当前URL。
咱们在百度的控制台输入
window.history.pushState(null, null, "https://www.baidu.com/?name=zzz")
此时url变成了这样
每次改变 url 页面并无刷新,一样根据上文所述,浏览器会产生历史记录。这就是实现页面无刷新状况下改变 url 的前提,下面咱们说下第一个参数 状态对象
若是运行 history.pushState() 方法,历史栈对应的纪录就会存入 状态对象,咱们能够随时主动调用历史条目。因此此时执行history.go(-1),就能够回到上一个状态(就是使url变成https://www.baidu.com/?name=zzz以前的状态)
官方文档提供了 popstate
事件,当咱们在历史记录中切换时就会产生 popstate
事件。对于触发 popstate
事件的方式,各浏览器实现也有差别,咱们能够根据不一样浏览器作兼容处理。
咱们常常在 url
中看到 #
,这个 #
有两种状况,一个是咱们所谓的锚点,好比典型的回到顶部按钮原理、Github
上各个标题之间的跳转等,路由里的 #
不叫锚点,咱们称之为 hash
,大型框架的路由系统大多都是哈希实现的。
基于hash的前端路由优势是:能兼容低版本的浏览器
以 hash 形式(也可使用 History API 来处理)为例,当 url 的 hash 发生变化时,触发 hashchange 注册的回调,回调中去进行不一样的操做。
react-router
的底层原理就是依赖了history
,后文将介绍实现原理。