react-router 快速上手教程(源码分析以及实现原理~~~)

react-router路由

「前言」

react-router 工具库其实也没什么好写,毕竟只要有一点 React 基础肯定就知道或者使用过 react-router。今天阅读 react-router 源码的时候突然想到一些好玩的东西。

这篇文章我记录我自己的心路历程,从根源上理解 react-router

「想象之中」

react 组件化的思想让开发者开发项目时就像拼「拼图🧩」一样,把多个组件拼接成一个项目。有些情况,我们只是在某个位置替换不同的组件,而不需要整个页面都重新加载。

举个例子🌰,常见的 CMS 系统布局,头部+左侧菜单栏都是固定的,变化的仅仅是右下内容区域。一种实现方式可以通过一种 state 状态来控制右下内容区域的需要渲染的内容组件,但是这种方式只能在当前 session 下可控,一旦刷新了页面,之前的 state 状态都会丢掉。显然对于一个项目来说这是不合理的。

组装

浏览器的 URL 内容是一个很好的记录页面状态的信息。SPA 形式之前,不同的 URL 都会向服务器发送请求,然后服务器返回一个完整的 HTML 页面。 SPA 形式下,URL 路由的变化只会在 浏览器端处理,所以组装页面的任务就交给了浏览器。

此时 react-router 出现了,通过使用 react-router 以及阅读 react-router 源码,发现 react-router 不过就是基于 URL 内容变化的「智能拼图工具」。

「源码分析」

react-router 源码提供了 路由必需的基础组件,对于 web 应用还需要适配 react-router-dom,源码结构如下图。其中包含了包工程结构以及右边 react-router 导出的组件列表。

react-router源码地址
「简单例子」
import {
  BrowserRouter,
  Route,
  Switch,
from "react-router-dom";
ReactDOM.render(
  <BrowserRouter>
    <Switch>
      <Route path='/' exact={true} component={App1} />
   <Route path='/app2' component={App1} />
      <Route path='/app2' component={App2} />
      <Route path='/app3' component={App3} />
    </Switch>
  </BrowserRouter>
,
  document.getElementById("root")
);

通过 简单例子 代码可以看出来 react-router 组件使用结构。<Route> 组件中包含需要渲染的业务组件,path属性决定什么情况渲染业务组件 。

最外层需要包裹一层 <BrowserRouter> 组件,从源码可以看出 Router 中嵌套了两层 React 的 Context:RouterContextHistoryContext

image-20201119184313852

RouterContext 给子组件消费者提供了 「history」「location」「match」「staticContext」四个属性。

HistoryContext 提供给子组件消费者提供了「history」属性。

Route 组件的作用是从 Router 组件的上下文中解构出属性,并同时组装自己props属性,然后新建一个 RouterContext 上下文并将props传递给业务组件。

image-20201119225039823

通过简单例子可以看出,从项目的入口列出 Route 列表,就是把整个页面当作一个拼图,然后通过路由替换整个页面。具体的业务组件中需要替换某一块区域,那么就在需要替换的地方列出 Route 列表。

「嵌套例子」
// src/App1.jsx
import React, { useState } from "react";
import { Layout, Menu } from "antd";
import { Route, Switch, Link } from "react-router-dom";

const { Header, Content, Sider, Footer } = Layout;

export default function App1({ routes = [] }) {
  const [selecgtKey, setSelectKey] = useState([window.location.pathname]);
  return (
     ...
        <Content>
        //核心代码
            <Switch>
              {routes.map((route, inx) => {
                return (
                  <Route
                    key={inx}
                    path={route.path}
                    exact={route.exact}
                    render={() => <route.component routes={route.routes} />}
                  />
                );
              })}
            </Switch>
        </Content>
    ...
  );
}
image-20201119231212160

嵌套代码只替换效果图中红框内容,只需要在 App1业务组件中再添加 <Route> 列表作为拼图占有区

路由会先匹配到外层父组件,然后再匹配父组件中Route组件。所以只要我想,我能一直套娃下去。

image-20201119232221120

「路由用法」

  • 所需 npm 包

npm install react-router

npm install react-router-dom

// 非必须

npm install react-router-config

「组件列表」
  • Router
    • StaticRouter
    • MemoryRouter
    • HashRouter
    • BrowserRouter
    • NativeRouter
  • Switch
  • Route
  • Redirect
  • Prompt
  • Link
    • NavLink
  • withRouter
「组件详情」
  • Router

    属性说明
    history
    staticContext
    children
    • BrowserRouter
    属性说明
    basename
    forceRefresh
    getUserConfirmation
    keyLength
    children
    • HashRouter
    属性说明
    basename
    getUserConfirmation
    hashType
    children
  • Route

    属性说明
    path
    component
    render
    children
    exact
    strict
    sensitive
    location
  • Switch

    属性说明
    location
    children
  • Redirect

    属性说明
    push
    from
    to
  • Prompt

    属性说明
    when
    message
  • Link

    属性说明
    innerRef
    replace
    target
    to
    onClick
    • NavLink (属性包含 Link )
    属性说明
    activeClassName
    activeStyle
    className
    style
    exact
    isActive
    location
    sensitive
    strict

「文章推荐」

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乐闻x

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

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

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

打赏作者

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

抵扣说明:

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

余额充值