React@16.x(46)路由v5.x(11)源码(3)- 实现 Router

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


以上。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雪天的夏风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值