将你的 React 应用组织成模块

2025-06-11

将你的 React 应用组织成模块

第一次在这里发帖,也是我多年的读者。觉得是时候回馈一下了。

我从事软件开发八年,最后两年一直在做 React 开发。之前用过原生 JavaScript 和 jQuery,但不得不说,我爱上了 React。

这篇文章将详细介绍我们如何组织我们的 React 应用程序。

这篇文章还假设您已经知道如何设置和使用 React(即这不是入门文章)。

让我们开始吧!

简介

我厌倦了待办事项 - 因此我们的虚构 shell 应用程序是游戏工作室的错误跟踪器,允许 alpha 和 beta 测试人员报告错误。

它有四个模块:仪表板、游戏、用户、分析。

虚构应用程序的屏幕截图

这种方法的优点在于,父应用对子模块没有任何具体的了解。它只知道自己拥有哪些模块。每个模块管理自己的位置和数据。你无需在父应用的任何地方添加<Route /><Link></Link>- 这些都由子应用定义。

这篇文章的代码在 GitHub 上。

GitHub 徽标 jjwilliams42 / dev-react-modules

如何使用模块组织 React 应用程序的示例

这是我的 dev.to 文章《将您的 React 应用程序组织成模块》的附带示例存储库

它展示了如何使用模块进行 React 开发。

我们正在构建的虚构 shell 应用程序是游戏工作室的错误跟踪器,允许 alpha 和 beta 测试人员轻松报告错误。

该项目由Create React App引导

可用脚本

在项目目录中,您可以运行:

npm start

以开发模式运行应用程序。
打开http://localhost:3000在浏览器中查看。

如果您进行编辑,页面将重新加载。
您还将在控制台中看到任何 Lint 错误。

npm test

以交互式监视模式启动测试运行器。有关更多信息,请参阅有关运行测试
的部分。

npm run build

将生产环境的应用程序构建到build文件夹中。
它在生产模式下正确打包 React,并优化构建以获得最佳效果……

入门

让我们开始实际的编码吧!

如果你没有 create-react-app,请使用 安装它npm install -g create-react-app。然后...

create-react-app dev-react-modules
cd dev-react-modules
npm install react-router-dom --save
yarn start

我不会详细说明所应用的样式,您可以在GitHub repo中查看。

创建模块

在 src 文件夹下,我们首先创建模块结构。它看起来像这样:

  • 模块
    • 分析
    • 仪表板
    • 游戏
    • 用户

在每个模块的文件夹中,添加一个 index.js

src\modules\Analytics\index.js



import React from 'react';

const Analytics = () => (
    <div>Analytics Module</div>
);

export default {
    routeProps: {
        path: '/analytics',
        component: Analytics
    },
    name: 'Analytics',
}



Enter fullscreen mode Exit fullscreen mode

src\modules\Dashboard\index.js



import React from 'react';

const Dashboard = () => (
    <div>Dashboard Module</div>
);

export default {
    routeProps: {
        path: '/',
        exact: true,
        component: Dashboard,
    },
    name: 'Dashboard',
};



Enter fullscreen mode Exit fullscreen mode

src\modules\游戏\index.js



import React from 'react';

const Games = () => (
    <div>Games Module</div>
);

export default {
    routeProps: {
        path: '/games',
        component: Games,
    },
    name: 'Games',
};



Enter fullscreen mode Exit fullscreen mode

src\modules\Users\index.js



import React from 'react';

const Users = () => (
    <div>Users Module</div>
);

export default {
    routeProps: {
        path: '/users',
        component: Users,
    },
    name: 'Users',
};



Enter fullscreen mode Exit fullscreen mode

这里没什么特别的,我们创建了模块及其默认导出。但我们不是只导出一个组件(让父组件自行协调),而是导出模块存在所需的一切。这可以扩展到包括模块主题、导航图标、所需权限等等……

我喜欢这个功能,因为我不需要改变父级来添加模块。我只需要……添加一个模块。

让我们分解一下导出,我在下面添加了一些评论。



export default {
    routeProps: { // This gets passed straight to react-router
        path: '/users', // Where the module lives in the nav hierarchy
        component: Users, // The actual component itself
    },
    name: 'Users', // The name of the module
};


Enter fullscreen mode Exit fullscreen mode

你可以把导出结构想象成父模块和子模块之间的契约。父模块说,我不关心有多少个模块,我只需要这些东西来渲染你。

现在我们需要导出所有这些模块。在 modules 文件夹中,创建一个 index.js 文件。

src\modules\index.js



import Analytics from './Analytics';
import Dashboard from './Dashboard';
import Games from './Games';
import Users from './Users';

export default [
    Dashboard,
    Analytics,
    Games,
    Users
];


Enter fullscreen mode Exit fullscreen mode

这里我们导出的是模块列表。这正是父级所需要的。

创建家长应用程序

现在我们的子模块都已完成,让我们将它们全部整合到主 App.js 中。

src\App.js



import React from 'react';
import { useState } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import logo from './logo.svg';
import './App.css';

import modules from './modules'; // All the parent knows is that it has modules ...

function App() {
  const [currentTab, setCurrentTab] = useState('dashboard');

  return (
      <Router>
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <ul className="App-nav">
              {modules.map(module => ( // with a name, and routes
                  <li key={module.name} className={currentTab === module.name ? 'active' : ''}>
                    <Link to={module.routeProps.path} onClick={() => setCurrentTab(module.name)}>{module.name}</Link>
                  </li>
              ))}
            </ul>
          </header>
          <div className="App-content">
            {modules.map(module => (
              <Route {...module.routeProps} key={module.name} />
            ))}
          </div>
        </div>
      </Router>
  );
}


Enter fullscreen mode Exit fullscreen mode

让我们来分析一下。

import modules from './modules';

正如我之前所说,父级只需要知道它有模块。在这里,我们导入它们。



<ul className="App-nav">
  {modules.map(module => (
      <li key={module.name} className={currentTab === module.name ? 'active' : ''}>
        <Link to={module.routeProps.path} onClick={() => setCurrentTab(module.name)}>{module.name}</Link>
      </li>
  ))}
</ul>


Enter fullscreen mode Exit fullscreen mode

在这里,父级知道模块有一个名称和一个链接(因为它是一个合同,记得吗?),所以它可以动态构建导航菜单。



<div className="App-content">
  {modules.map(module => (
    <Route {...module.routeProps} key={module.name} />
  ))}
</div>


Enter fullscreen mode Exit fullscreen mode

这里,父级也知道模块有一个带组件的路由,因此它可以动态地渲染<Route />

现在您有一个自组织、模块化的 React 应用程序。

但请稍等,还有更多!

添加新模块

我们遗漏了错误跟踪器的一个关键模块:错误。

我们的新结构的优点在于,我所要做的就是将新模块添加到导出列表中。

src\modules\Bugs\index.js



import React from 'react';

const Bugs = () => (
<div>Bugs Module</div>
);

export default {
routeProps: {
path: '/bugs',
component: Bugs,
},
name: 'Bugs',
};

Enter fullscreen mode Exit fullscreen mode




src\modules\index.js




import Analytics from './Analytics';
import Bugs from './Bugs'; // added
import Dashboard from './Dashboard';
import Games from './Games';
import Users from './Users';

export default [
Dashboard,
Games,
Bugs, // added
Users,
Analytics,
];

Enter fullscreen mode Exit fullscreen mode




结论

我已经使用这个结构好几年了,非常喜欢它。它在我们的应用中扩展了不少,但我想让这篇文章保持简洁。

这也并非我的功劳。几年前刚开始使用 React 时,我很幸运能与一位资深 React 专家共事。他教会了我这种结构(并且一直在教我良好的 React 实践)。我喜欢向其他开发者学习!

有什么想法、问题或建议吗?你是如何组织你的 React 项目的?

鏂囩珷鏉ユ簮锛�https://dev.to/jack/organizing-your-react-app-into-modules-d6n
PREV
注意缺失的外键索引:Postgres 性能陷阱
NEXT
如何构建和发布你自己的扩展到 VS Code Marketplace