目录
- 1,Router 的结构
- 2,实现
- 2.1,react-router
- 1,matchPath.js
- 2,Router.js
- 3,RouterContext.jsx
- 4,index.jsx
- 2.2,react-router-dom
- BrowserRouter.jsx
- index.jsx
1,Router 的结构
1,react-router 用于注入 history
上下文对象,但 history
对象是别人传递给它的。
2,react-router-dom 使用了 react-router,并传递创建 history
对象。
大致如下:
1,react-router-dom.js
import { createBrowserHistory } from "history"
import { Router } from "./react-router"
export default class BrowserRouter extends Component {
history = createBrowserHistory(this.props)
render() {
return <Router history={this.history}>
{this.props.children}
</Router>
}
}
2,react-router.js
export default class Router extends Component {
ctxValue = { //上下文中对象
history: {},
location : {},
match : {},
}
render() {
return <ctx.Provider value={this.ctxValue}>
{this.props.children}
</ctx.Provider>
}
}
3,其他组件使用:
import { BrowserRouter as Router } from "./react-router-dom";
export default function App() {
return <Router></Router>
}
2,实现
项目目录
react-router
-- index.js
-- matchPath.js
-- Router.js
-- RouterContext.js
react-router-dom
-- index.js
-- BrowserRouter.js
2.1,react-router
1,matchPath.js
用于获取并组装 match
对象,参考 这篇文章。
2,Router.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import ctx from "./RouterContext";
import matchPath from "./matchPath";
export class Router extends Component {
static propTypes = {
history: PropTypes.object.isRequired,
children: PropTypes.node,
};
state = {
location: this.props.history.location, // location 作为状态,是因为切换路由时会发生变化。
};
componentDidMount() {
this.unListen = this.props.history.listen((nextLocation, action) => {
this.props.history.action = action;
this.setState({
location: nextLocation,
});
});
}
componentWillUnmount() {
this.unListen();
}
ctxValue = {};
render() {
this.ctxValue.history = this.props.history;
this.ctxValue.location = this.state.location;
this.ctxValue.match = matchPath("/", this.state.location.pathname);
return <ctx.Provider value={this.ctxValue}>{this.props.children}</ctx.Provider>;
}
}
3,RouterContext.jsx
提供上下文对象。
import { createContext } from "react";
const context = createContext();
context.displayName = "Router"; // 在 React 插件调试时,显示的名字。
export default context;
4,index.jsx
export * from "./Router";
2.2,react-router-dom
BrowserRouter.jsx
import React, { Component } from "react";
import { createBrowserHistory } from "history";
import { Router } from "../react-router";
export class BrowserRouter extends Component {
history = createBrowserHistory();
render() {
return <Router history={this.history}>{this.props.children}</Router>;
}
}
index.jsx
export * from "./BrowserRouter";
接下文实现 Route
以上。