react-router&dom的源码分析
# react-router-dom
react-router-dom是react的路由,它帮助我们在项目中实现单页面应用,它提供给我们两种路由一种基于hash段实现的HashRouter,一种基于H5Api实现的BrowserRouter。
环境配置
npm i react react-dom react-router-dom @babel/preset-react -D
1
webpack.config.js,在js的options配置加一个preset
将index.js改成这样。
import React from 'react'
import ReactDom from 'react-dom'
import { BrowserRouter, Route, Link } from 'react-router-dom'
function App() {
return (
<BrowserRouter>
<Link to='/home'>home</Link>
<Link to='/about'>about</Link>
<Route path='/home' render={()=><div>home</div>}></Route>
<Route path='/about' render={()=><div>about</div>}></Route>
</BrowserRouter>
)
}
ReactDom.render(<App></App>,document.getElementById('root'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public/index.html
<div id="root"></div>
1
# browserRouter实现
首先我们在index.js新建一个BrowserRouter.js文件,我们来实现自己BrowserRouter。
既然要实现BrowserRouter,那这个文件就得有三个组件BrowserRouter,Route,Link。
# BrowserRouter组件
BrowserRouter组件主要做的是将当前的路径往下传,并监听popstate事件,所以我们要用Consumer
# Rouer组件的实现
Router组件主要做的是通过BrowserRouter传过来的当前值,与Route通过props传进来的path对比,然后决定是否执行props传进来的render函数
# Link组件的实现
Link组件主要做的是,拿到prop,传进来的to,通过PushState()改变路由状态,然后拿到BrowserRouter传过来的onChangeView手动刷新视图
使用
把刚才在index.js使用的react-router-dom换成这个文件路径就OK
# hashRouter的实现
hashRouter就不一个一个组件的说了,跟BrowserRouter大同小异,直接贴完整代码
const { Consumer, Provider } = React.createContext();
export class BrowserRouter extends React.Component {
constructor(props) {
super(props);
this.state = {
currentPath: this.getParams.bind(this)(window.location.pathname),
};
}
onChangeView() {
const currentPath = this.getParams.bind(this)(window.location.pathname);
this.setState({ currentPath });
}
getParams(url) {
return url;
}
componentDidMount() {
window.addEventListener("popstate", this.onChangeView.bind(this));
}
componentWillUnmount() {
window.removeEventListener("popstate", this.onChangeView.bind(this));
}
render() {
return (
<Provider
value={{
currentPath: this.state.currentPath,
onChangeView: this.onChangeView.bind(this),
}}
>
<div>
{React.Children.map(this.props.children, function (child) {
return child;
})}
</div>
</Provider>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
上次更新: 2022/04/15, 05:41:29