模仿react-router实现

2019-11-07  本文已影响0人  key君

history是react-router-dom里面的

src/pages/MyRouterPage.js
import React, { Component } from "react";
// import { BrowserRouter, Link, Route } from "react-router-dom";
import { BrowserRouter, Link, Route } from "../my-react-router-dom";
import HomePage from "./HomePage";
import UserPage from "./UserPage";

export default class MyRouterPage extends Component {
  render() {
    return (
      <div>
        <h3>MyRouterPage</h3>
        <BrowserRouter>
          <Link to="/">首页</Link>
          <Link to="/user">用户中心</Link>
          <Route path="/" exact component={HomePage} />
          <Route path="/user" component={UserPage} />
        </BrowserRouter>
      </div>
    );
  }
}

my-react-router-dom.js

import React, { Component, useContext } from "react";
import { createBrowserHistory } from "history";

const RouterContext = React.createContext();

export class BrowserRouter extends Component {
  constructor(props) {
    super(props);
    //获取history history是解决了a标签禁止浏览器跳转事件之后 链接不跳转的问题 其实就是跳转链接而页面不跳动
    this.history = createBrowserHistory();
    //把history作为参数
    this.state = {
      location: this.history.location,
    };
    //监听history变化
    this.unlisten = this.history.listen(location => {
      this.setState({ location });
    });
    console.log("this", this.history);
  }
  //移除监听
  componentWillUnmount() {
    if (this.unlisten) {
      this.unlisten();
    }
  }
  render() {
    //获取节点 直接显示
    const { children } = this.props;
    return (
      // context传出参数
      <RouterContext.Provider
        value={{
          history: this.history,
          location: this.state.location,
        }}
      >
        {children}
      </RouterContext.Provider>
    );
  }
}

export function Route(props) {
  //拿到传进来的path和组件
  const { path, component: Cmp } = props;
  //useContext用来拿Provider传出的参数
  const ctx = useContext(RouterContext);
  //拿到location
  const { location } = ctx;
  //如果本页面路径跟跳转路径一致就显示
  const match = path === location.pathname;
  return match && <Cmp />;
}

export class Link extends Component {
  //拿到location.history push到对应路径
  handleClick = (event, history) => {
    const { to } = this.props;
    event.preventDefault();
    history.push(to);
  };
  render() {
    const { children, to } = this.props;
    return (
      // Consumer 拿到location 传给点击事件 href就是跳转的路径
      <RouterContext.Consumer>
        {ctx => {
          return (
            <a
              href={to}
              onClick={event => this.handleClick(event, ctx.history)}
            >
              {children}
            </a>
          );
        }}
      </RouterContext.Consumer>
    );
  }
}

上一篇 下一篇

猜你喜欢

热点阅读