React Router 原理分析
前言
如果我们开发 React 的 SPA(单页应用 single page web application),不可避免的接触 router 的概念,但是他是怎么实现的呢?本次基于 react-router v4
HashRouter
HashRouter
其实原理是通过window.addEventListener('hashchange', callback)
事件来实现的,其特色就是会出现一个#
井号的含义
其实是锚点,指的是阅读到什么位置,最常见的就是上面这个标题,查看html
后你会发现id
等于井号的含义
,当点击右侧阅读导航的时候,浏览器url
后面就会加上#井号的含义
。
特性
- 由于
#
实际上是控制浏览器动作的,对服务器没有任何作用,所以在它之后的东西并不会涵盖在http
请求:https://yeungkc.com/2019/07/06/web-react-router/#井号的含义
实际上 http 请求只有 https://yeungkc.com/2019/07/06/web-react-router/ - 同因为是控制浏览器动作,改变
#
只会滚动到相应的位置,并不会重新加载网页 - 改变
#
会改变访问历史,即是你点击多次标题导致滚动位置变化,后退的时候也是回到之前的位置 window.location.hash
可以读取和写入,写入的时候增加历史记录
BrowserRouter
除非低版本没办法,拥有一个多余的#
总是不好的,更为优雅的方法是利用window.addEventListener('popstate', callback)
方法来进行前进后退的监听,甚至在不用使用window.location.hash = '#foo'
这种方式,直接使用window.history
来控制变得优雅简单许多,可惜的是这个是HTML5
API,可幸的是大部分都有用上了
使用
- 监听
1
2
3window.addEventListener("popstate", e => {
const path = e.state && e.state.path;
}); History.back()
:移动到上一个网址,等同于点击浏览器的后退键。对于第一个访问的网址,该方法无效果History.forward()
:移动到下一个网址,等同于点击浏览器的前进键。对于最后一个访问的网址,该方法无效果History.go()
:接受一个整数作为参数,以当前网址为基准,移动到参数指定的网址,比如go(1)
相当于forward()
,go(-1)
相当于back()
。如果参数超过实际存在的网址范围,该方法无效果;如果不指定参数,默认参数为 0,相当于刷新当前页面History.pushState()
:方法用于在历史中添加一条记录,有三个参数state
:一个与添加的记录相关联的状态对象,主要用于popstate
事件。该事件触发时,该对象会传入回调函数。也就是说,浏览器会将这个对象序列化以后保留在本地,重新载入这个页面的时候,可以拿到这个对象。如果不需要这个对象,此处可以填null
title
:新页面的标题。但是,现在所有浏览器都忽视这个参数,所以这里可以填空字符串url
:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址History.replaceState()
:用来修改History
对象的当前记录,其他都与pushState()
方法一模一样