zzxworld

使用 React router 6

在上一篇介绍使用 React 的文章里,我按照自己的需求以 Webpack 为打包工具,搭建了一个最基础的 React 开发环境。它虽然已经可以让我开始用上 React 的组件功能,但从我实际项目的需求出发,依然还缺少一些实用的辅助扩展。React router 就是其中之一。

我准备使用 React 的项目是一个 OA 系统,涉及到从采购,产品,库存以及销售订单等多方面的业务功能。这些不同的业务功能会有自己不同的访问地址。作为一个前后端完全分离的项目,我需要在前端搞定这些功能界面的访问路径以及对应界面的显示,React router 应该能够帮我解决这个问题。

所以这次我要开始尝试把 React router 集成到我的基础环境中来。另外出于实际应用的需要,我还会尝试研究一下访问不同页面时的「按需加载」功能。因为实际项目中会包含各种不同的业务功能,如果全打包在一个 js 文件中,会给系统访问带来一些瓶颈或影响。所以最好是在访问时再去加载页面需要的 js 文件。

以上是我的需求和考虑,明确了目的,下面开始实操。

注意:本文是基于我上一篇文章中搭建的 React 基础环境来试验 React router 功能的,所以如果你也有兴趣准备尝试一下,请按照我上篇文章的步骤完成 React 基础环境的搭建。链接在此:手动搭建基于 Webpack 的 React 项目开发环境

使用 React route

第一步:安装 React router。进入项目目录后,依然还是使用 yarn 命令:

yarn add react-router-dom

第二步:使用 React router。编辑 src/main.js 文件,修改为如下代码:

import React from 'react';
import ReactDOM from 'react-dom';
import {HashRouter, Routes, Route, Link} from 'react-router-dom';

// 首页
function ViewHome() {
    return (
        <div>
            <h1>HomePage</h1>
            <p>This is homepage.</p>
        </div>
    );
}

// 关于页面
function ViewAbout() {
    return (
        <div>
            <h1>About</h1>
            <p>This is about page.</p>
        </div>
    );
}

// 页面布局
function AppLayout() {
    return (
        <HashRouter>
            <nav>
                <Link to="/">Home</Link> | <Link to="/about">Abount</Link>
            </nav>
            <Routes>
                <Route path="/" element={<ViewHome />} />
                <Route path="/about" element={<ViewAbout />} />
            </Routes>
        </HashRouter>
    );
}

// 渲染布局组件
ReactDOM.render(<AppLayout />, document.getElementById('app'))

上面的代码简单介绍一下,相比这个文件之前的代码,这次主要的调整如下:

  1. 代码第三行引入了 React router 中的一些需要使用的工具组件。比如前端专用的 「Hash-bang」地址路由组件 HashRouter,以及定义路由页面的 RoutersRoute,还有定义链接跳转的 Link
  2. 创建了两个页面组件。一个是首页页面的组件 ViewHome,一个是关于页面的组件 ViewAbout
  3. 创建了一个布局组件 AppLayout。在这个组件里使用 React router 提供的工具,定义了项目入口页面的导航菜单和相关地址与页面组件的绑定关系。

完成以上两步,React router 就在这个实验小项目中用起来了。执行 yarn start 看看效果:

image-20211116110730919

点击 About 链接后:

image-20211116110804441

完美!而且和点击普通的网页链接不同,这种前端路由的方式没有页面重新加载的过程,所以在交互过程的响应体验上有点类似于使用桌面软件的感觉。

按需加载页面代码

接下来测试我另外一个想法:按需加载。目前代码中的「首页」和「关于页面」是被打包在一起的,我希望可以被打包成两个不同的 js 文件。在我要进入对应页面时,程序再自动加载页面的 js 代码并执行。

这次不需要安装任何扩展库,React 已经提供好了相应的函数和组件功能。在使用这些现成工具前,需要先调整一下代码。首先是不同页面的代码不能放在同一个文件了。那就创建一个专门的目录来存放这类代码:

make src/pages

以上命令在源码目录创建了一个 pages 目录。接下来在这个目录里面分别创建「首页」和「关于页面」的组件代码。首先是「首页」的:

touch src/pages/home.js

这个文件的代码如下:

import React from 'react';

export default () => {
    return (
        <div>
            <h1>HomePage</h1>
            <p>This is homepage.</p>
        </div>
    );
}

然后是「关于页面」的:

touch src/pages/about.js

同样代码如下:

import React from 'react';

export default () => {
    return (
        <div>
            <h1>About page</h1>
            <p>This is about pages.</p>
        </div>
    );
}

基本就是把之前 src/main.js 目录里的两个页面组件代码搬过来了。

接下来就是把 src/main.js 文件的代码调整为如下:

import React, { Suspense, lazy } from 'react';
import ReactDOM from 'react-dom';
import { HashRouter, Routes, Route, Link } from 'react-router-dom';

const PageHome = lazy(() => import('./pages/home'))
const PageAbout = lazy(() => import('./pages/about'))

function AppLayout() {
    return (
        <HashRouter>
            <nav>
                <Link to="/">Home</Link> | <Link to="/about">Abount</Link>
            </nav>
            <Routes>
                <Route path="/" element={
                        <Suspense fallback={<div>Loading...</div>}>
                            <PageHome />
                        </Suspense>
                    } />
                <Route path="/about" element={
                        <Suspense fallback={<div>Loading...</div>}>
                            <PageAbout />
                        </Suspense>
                    } />
            </Routes>
        </HashRouter>
    );
}

ReactDOM.render(<AppLayout />, document.getElementById('app'))

这次相对于本文件上一次的调整,主要有这些变化:

  1. 从 React 库中引入了 Suspense 组件和 lazy 函数,通过他俩的配合来实现按需加载功能。
  2. 移除了本文件中两个页面的组件代码,通过 lazyimport 来实现加载引入。
  3. 对路由的 element 属性做了调整,通过 Suspense 组件包装了一下页面组件。在动态加载页面 js 文件时,如果等待的响应时间较长,Suspense 组件能提供一个比较人性化的 Loading 提示。

来体验一下调整后的效果。这次需要配合浏览器的控制台才能看到效果了。首先是进入首页的效果:

image-20211116121011323

控制台显示加载了两个 js 文件,最下面一个就是首页的。

点击一下「关于页面」的链接 About,效果如下:

image-20211116121216878

随着点击操作,控制台上显示请求了一个新的 js 文件,通过文件名就能看出是关于页面的。

目的达成,离我把 React 应用到实际项目又近了一步。

相关文章