Appearance
实现路由
本节目标:理解“实现路由”的核心思路,并能把它用于实际开发或面试表达。
Src\react-router-dom\index.js
export* from
'../react-router';
export{defaultas
HashRouter}from
'./HashRouter';
export{defaultas
BrowserRouter}from
'./BrowserRouter';Src\react-router-dom\HashRouter.js
importReact from
'react';
import{ Router } from
'../react-router';
import{ createHashHistory } from
'history';
classHashRouter extends
React.Component{history =
createHashHistory()//HashRouter的history实例属性会指向用hash实现的历史对象
render(){return (
<Routerhistory={this.history}>{this.props.children}</Router> `)`
}
}
exportdefault
HashRouter;
/*** createHashHistory和createBrowserHistory* 都 会反回一个history对象,对象的方法和API是完全相同的,只是内部的实现原理不一样 */
Src\react-router\index.js
export {default as Router} from './Router';
export {default as Route} from './Route';
export {default as __RouterContext} from './RouterContext';Src\react-router\RouterContext.js
importReact from
'react';
exportdefault
React.createContext({});Src\react-router\Router.js
import React from 'react';
import RouterContext from './RouterContext';
class Router extends React.Component {
constructor(props) {
super(props);
this.state = {
location: props.history.location
}
//监听历史对象路径变化,如果路径发生变化的话执行回调
this.unlisten = props.history.listen((location) => {
this.setState({ location })
});
}
componentWillUnmount() {
this.unlisten && this.unlisten();
}
render() {
let value = { history: this.props.history, location: this.state.location };
return (
<RouterContext.Provider value={value}>
{this.props.children}
</RouterContext.Provider>
)
}
}
export default Router;Src\react-router\Route.js
import React from 'react';
import RouterContext from './RouterContext';
class Route extends React.Component {
static contextType = RouterContext;
render() {
const { history, location } = this.context;
const { path, component: RouteComponent, exact = false } = this.props;
const match = exact ? location.pathname === path : location.pathname.startsWith(path);// /user /user
const routeProps = { history, location };
let renderElement = null;// null也一个合法的react渲染节点,代表我们render的返回值,代表此组件将要渲染的内容;
if (match) {
//React.createElement(RouteComponent,routeProps);
renderElement = <RouteComponent {...routeProps} />
}
return renderElement
}
}
export default Route;Src\history\createHashHistory
function createHashHistory() {
const history = {
action: 'POP',
go,
goBack,
goForward,
push,
listen,
location: {}
}
return history;
}
export default createHashHistory;Src\history\createBrowserHistory
function createBrowserHistory() {
const globalHistory = window.history;
let listeners = [];
function go(n) {
globalHistory.go(n);
}
function goBack() {
globalHistory.back();
}
function goForward(n) {
globalHistory.forward()
}
const history = {
action: 'POP',
go,
goBack,
goForward,
push,
listen,
location: {}
}
return history;
}
export default createBrowserHistory;