Skip to content

实现路由 ​

本节目标:理解“实现路由”的核心思路,并能把它用于实际开发或面试表达。

Src\react-router-dom\index.js
export

* from

'../react-router';
export
{default

as

HashRouter}

from

'./HashRouter';
export
{default

as

BrowserRouter}

from

'./BrowserRouter';
Src\react-router-dom\HashRouter.js
import

React from

'react';
import

{ Router } from

'../react-router';
import

{ createHashHistory } from

'history';
class

HashRouter extends

React.Component

{history =

createHashHistory()//HashRouter

的history实例属性会指向用hash实现的历史对象

render()

{return (

<Router
history={this.history}>
{this.props.children}
</Router>
 `)`
}
}
export

default

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
import

React from

'react';
export

default

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;

本站总访问 — 次