react-router是配合react使用的路由控件,功能也很强大,而了解其设计原理开发者来说是有必要也是有帮助的。接下来探讨一下react-router的设计原理。
了解react-router原理,首先要知道几个概念:h5 history对象,js history库,react-router是基于它们实现的。
h5 history
可以很清楚的看到history对象的属性和方法:
其中使用 pushState(),replaceState()时,浏览器url改变,但是页面并不刷新
每次但我们触发history.back(), History.forward()或点击浏览器的前进后退按钮时,都会触发popstate事件。
每次触发history.back(), History.forward()或点击浏览器的前进后退按钮时,都会触发popstate事件。
所以如果使用history做为路由基础,就需要使用history.pushState和history.replaceState来改变url的值而不刷新页面,然后通过popstate事件执行页面的前进与后退
h5 demo 注意:该例子需要创建一个本地服务器启动应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<a onClick="go('/a')">pageALink</a>
<a onClick="go('/b')">pageBLink</a>
<span id='body'></span>
<script>
console.log(window.history)
function go (pathname){
window.history.pushState({},null,pathname);
document.getElementById('body').innerHTML = window.location;
}
//这里主要处理浏览器前进后退功能,不加下面的代码就无法实现前进后退功能
window.addEventListener('popstate',(e)=>{
let pathname = window.location;
document.getElementById('body').innerHTML = window.location;
})
</script>
</body>
</html>
history 库
history是一个第三方js库,借鉴HTML5 history对象的理念,在其基础上又扩展了一些功能,用来管理历史记录,可以兼容不同的浏览器和不同的环境,根据不同的环境提供了三种不同的API。
HashHistory:针对老版本的浏览器,主要通过Hash实现。
BrowserHistory:针对较高版本的浏览器,主要通过H5的History实现。
MemoryHistory:主要通过内存中的历史记录实现。
History支持发布/订阅功能,当history发生改变的时候,可以自动触发订阅的函数,再对比一些两者api的异同。以下是history库的:
const history = {
length, // 属性,history中记录的state的数量
action, // 属性,当前导航的action类型
location, // 属性,location对象,封装了pathname、search和hash等属性
push, // 方法,导航到新的路由,并记录在history中
replace, // 方法,替换掉当前记录在history中的路由信息
go, // 方法,前进或后退n个记录
goBack, // 方法,后退
goForward, // 方法,前进
canGo, // 方法,是否能前进或后退n个记录
block, // 方法,跳转前让用户确定是否要跳转
listen // 方法,订阅history变更事件
};
react-router实现
设计思想:对History进行了一次封装,使能够识别将url的变化与componet渲染进行匹配
- 根据BrowserRouter等不同的API针对H5的history的重构
- 结构的构建,同时对history属性进行注册。
- 在Router的componentWillMount中注册history的事件回调。
- 在Redirect中进行路径的计算,调用history.push/history.replace等更新history信息。
- Route中根据计算的匹配结果,进行页面首次渲染/页面更新渲染处理。
具体实现代码:参见github
参考:https://blog.csdn.net/qq_36223144/article/details/83247008