1

早期的路由都是后端实现的,直接根据 url 来 reload 页面,页面变得越来越复杂服务器端压力变大,随着 ajax 的出现,页面实现非 reload 就能刷新数据,也给前端路由的出现奠定了基础。我们可以通过记录 url 来记录 ajax 的变化,从而实现前端路由。

router url History hash

History API

大家可以查看MDN的文档:https://developer.mozilla.org/en-US/docs/Web/API/History
本文主要说两个新增的API history.pushStatehistory.replaceState(相同之处: 都会操作浏览器的历史记录,而不会引起页面的刷新。
不同之处: pushState会增加一条新的历史记录,而replaceState则会替换当前的历史记录。)

这两个 API 都接收三个参数,分别是状态对象(state) — 无论何时用户导航到新创建的状态,popstate事件都会被触发,并且事件对象的state属性都包含历史记录条目的状态对象的拷贝,默认null。

标题(title) — 标明将要进入的状态,默认null。

地址(URL) — 新的历史记录条目的地址,传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。默认为当前URL。

我们在百度的控制台输入

window.history.pushState(null, null, "https://www.baidu.com/?name=zzz")

此时url变成了这样

clipboard.png

状态对象(state) — 无论何时用户导航到新创建的状态,popstate事件都会被触发,并且事件对象的state属性都包含历史记录条目的状态对象的拷贝,默认null。

标题(title) — 标明将要进入的状态,默认null。

地址(URL) — 新的历史记录条目的地址,传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。默认为当前URL。

我们在百度的控制台输入

window.history.pushState(null, null, "https://www.baidu.com/?name=zzz")

此时url变成了这样

clipboard.png

每次改变 url 页面并没有刷新,同样根据上文所述,浏览器会产生历史记录。这就是实现页面无刷新情况下改变 url 的前提,下面我们说下第一个参数 状态对象

如果运行 history.pushState() 方法,历史栈对应的纪录就会存入 状态对象,我们可以随时主动调用历史条目。所以此时执行history.go(-1),就可以回到上一个状态(就是使url变成https://www.baidu.com/?name=zzz之前的状态)

clipboard.png

官方文档提供了 popstate 事件,当我们在历史记录中切换时就会产生 popstate 事件。对于触发 popstate 事件的方式,各浏览器实现也有差异,我们可以根据不同浏览器做兼容处理。

hash

我们经常在 url 中看到 #,这个 # 有两种情况,一个是我们所谓的锚点,比如典型的回到顶部按钮原理、Github 上各个标题之间的跳转等,路由里的 # 不叫锚点,我们称之为 hash,大型框架的路由系统大多都是哈希实现的。

基于hash的前端路由优点是:能兼容低版本的浏览器

以 hash 形式(也可以使用 History API 来处理)为例,当 url 的 hash 发生变化时,触发 hashchange 注册的回调,回调中去进行不同的操作。

react-router

react-router 的底层原理就是依赖了history,后文将介绍实现原理。


朱珍珍
75 声望7 粉丝

毕业于重庆邮电大学,暂就职在北京杏树林科技有限公司,JS开发