资讯专栏INFORMATION COLUMN

React 项目结构和组件命名规范

jay_tian / 1221人阅读

摘要:作为一个库,它没有规定项目的整体结构。位于的组件应命名为。组件根据其与组件或的相对路径进行相应命名。考虑这样一个场景,处于位置的组件会被命名为而不是。

React 作为一个库,它没有规定项目的整体结构。这很好,因为它给了我们自由去尝试不同的方法,并适应更适合我们的方式。另一方面,这可能会给React领域的开发人员带来一些困惑。

我将会在本文为大家展示我已经使用过一段时间并且效果不错的方式,这些方式没有通过重新造轮子来实现,而是通过将社区中的方案组合和提炼得到。

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!

目录结构

我经常遇到的一个问题是如何组织文件和目录结构。在这篇文章中,我们认为你已有一个最小的结构,就像用 create-react-app 创建的结构一样。

create-react-app 为我们生成了一个基础的项目,包含根目录还有诸如.gitignore, package.json, README.md, yarn.lock 的文件。

它还生成 publicsrc目录, src目录是我们保存源代码的地方。

请看下面的图片,以及描述的结构:

在这篇文章中,我们只关注src目录,src 之外保持不变。

容器和组件 (Containers and Components)

你可能已经在某些项目的根目录下看到了容器和展示组件之间的分离。我的意思是,在src中,在 src 目录下有 containers 目录和 components 目录:

src
├─ components 
└─ containers

但是,这种方法有一些问题,如下所示:

主观的规则:对于容器和展示组件,没有明确的规则。彼此之间的差异可能是主观的,当你在一个团队中时,很难让所有开发人员赞成并评判这个问题。

它没有考虑组件的动态性:即使当你决定某个组件适合于某个特定类型时,也很容易在项目生命周期中对其进行更改,使其从另一种类型变为另一种类型,最终迫使你把它从 components 挪到 containers 目录下,反之亦然。

允许两个具有相同名称的组件:组件的命名在应用程序中具有声明性和惟一性,以避免混淆每个组件的职责。但是,上面的方式破坏了具有相同名称的两个组件,一个是容器,另一个是展示示组件。

效率低下: 即使你在实现一个独立特性时,也不得不经常在 containerscomponents 目录下来回切换,因为一个独立特性有两种不同类型的组件是再正常不过的事情了。

还有一种方法,在模块内部保存containerscomponents分离:

src
└─ User
  ├─ components
  └─ containers

上述方法最大限度地减少了在项目树中不同层级目录切换的问题。然而,它会增加很多噪音。根据你的应用程序有多少模块,你最终会创建几十个containerscomponents 目录。

出于这些原因,当我们谈论组织目录和文件时,通过展示与容器的概念来拆分组件是无关紧要的。 也就是说,除页面外,我们将把所有组件放在 components 目录下。

即使在目录上区分展示组件和容器组件是没有太多必要的,了解它们之间的差异性依然是有必要的。如果你对这个话题还有疑问,建议阅读这篇文章:Presentational and Container Components
拆分和组合代码

components目录中,我们按模块/功能对文件进行分组。

在用户的增删改查中,我们只有User模块,结构是这样的

src
└─ components
  └─ User
    ├─ Form.jsx
    └─ List.jsx

当组件由多个文件组成时,我们将此组件及其文件放在具有相同名称的目录下。 例如:假设有一个包含Form.jsx样式的Form.css。 在这种情况下,你的结构如下:

src
└─ components
  └─ User
    ├─ Form
    │ ├─ Form.jsx
    │ └─ Form.css
    └─ List.jsx
测试文件与被测试的文件保持一致。在上面的例子中,Form.jsx 的测试文件会放在同一个文件夹下并且命名为 Form.spec.jsx
UI 组件

除了通过模块拆分组件之外,我们还在src/components中包含一个 UI 目录,以保留其中的所有通用组件。

UI 组件是通用的组件,不属于模块。 它们是可以保留在开源库中的组件,因为它们没有来自特定应用程序的任何业务逻辑。 这些组件的示例包括:按钮,输入,复选框,选择,模态框,数据可视化组件等等。

命名组件中的类

上面我们看到了如何构建目录并按模块分离我们的组件。 但是,还有一个问题:如何命名它们?

当我们谈论命名组件时,它涉及我们给类或定义组件的常量名称:

class MyComponent extends Component {
}
const MyComponent () => {};

如上所述,我们为组件提供的名称应该在应用程序中清晰且独特,以便更容易找到并避免可能的混淆。

当我们需要使用工具作为React Dev工具进行调试时,以及当应用程序中发生运行时错误时,组件的名称非常方便,错误总是与发生错误的组件名一起出现。

我们采用基于路径的组件命名方式,即根据相对于 components 文件目录的相对路径来命名,如果在此文件夹以外,则使用相对于 src 目录的路径。举个例子,组件的路径如果是 components/User/List.jsx,那么它就被命名为 UserList

当文件位于具有相同名称的组件中时,我们不需要重复该名称。 也就是说,components/User/Form/Form.jsx将被命名为UserForm而不是UserFormForm

上面的模式有一些好处,我们可以在下面看到:

便于在项目中搜索文件

如果编辑器支持模糊搜索,只需搜索名称UserForm就可以找到正确的文件

如果你想要在目录中搜索文件,可以很容易地通过组件的名字定位到它:

避免在导入重复名称

按照该模式,可以始终根据文件的上下文为组件命名。考虑到上面的表单,我们知道它是一个用户表单,但是由于我们已经在 User 目录中 ,所以不需要在组件文件名中重复这个单词。因此,我们只将它命名为Form.jsx

我最初使用 React 的时候喜欢用完整的名字来命名文件,但是这样会导致相同的部分重复太多次,同时引入时的路径太长。来看看这两种方式的区别:

import ScreensUserForm from "./screens/User/UserForm";
// vs
import ScreensUserForm from "./screens/User/Form";

在上面的示例中,可能无法看到从一种方法到另一种方法的优势。 但是应用程序名称多了话,就可以看到差异, 如下:

import MediaPlanViewChannel from "/MediaPlan/MediaPlanView/MediaPlanViewChannel.jsx";
// vs
import MediaPlanViewChannel from "./MediaPlan/View/Channel";

想象一下名称重复十几二十次的样子。

因此,我们根据文件 的上下文来命名文件,根据组件的相对位置来命名组件是一种更好的方式。

页面(Screen)

屏幕,顾名思义,就是我们在应用程序中展示出来的样子。

如果要对一个用户做增删改查的操作,我们需要有用户列表页面,创建新用户的页面以及编辑已有用户的页面。

我们将screens 保存在src根目录中的多带带文件夹中,因为它们将根据路由定义而不是模块进行分组:

src
├─ components 
└─ screens
  └─ User
    ├─ Form.jsx
    └─ List.jsx

考虑到项目使用react-router,我们将文件Root.jsx放在在screens目录下,并在其中定义所有应用程序路由。

Root.jsx 的代码可能像下面这样:

import React, { Component } from "react";
import { Router } from "react-router";
import { Redirect, Route, Switch } from "react-router-dom";

import ScreensUserForm from "./User/Form";
import ScreensUserList from "./User/List";

const ScreensRoot = () => (
  
    
      
      
      
    
  
);

export default ScreensRoot;

请注意,我们将所有页面放在一个目录中,这个目录以路由名称命名,user/ -> User/。尝试为每个父级路由建立一个目录,在这个目录中组织子路由。 在这种情况下,我们创建了User目录,并将List 页面和Form页面放入其中。这种方式使你看一眼 url 就能够轻松定位当前路由渲染的页面。

单个页面可用于渲染两条不同的路线,如上所述,其中包含用于创建和编辑用户的路线。

你可能会注意到所有组件都将Screen作为其名称的前缀。 当组件位于components 目录之外时,我们应该根据它到src文件夹的相对路径来命名。 位于src/screens/User/List.jsx 的组件应命名为ScreensUserList

创建 Root.jsx 后,目录的结构如下:

src
├─ components 
└─ screens
  ├─ User
  │ ├─ Form.jsx
  │ └─ List.jsx
  └─ Root.jsx

如果你对一个页面长什么样子还有疑问,看看下面的示例,它就是用户表单的页面。

import React from "react";
import UserForm from "../../components/User/Form/Form";

const ScreensUserForm = ({ match: { params } }) => (
  

{`${!params.id ? "Create" : "Update"}`} User

); export default ScreensUserForm;

最后,我们的应用程序结构如下:

src
├─ components 
│  ├─ User
│  │ ├─ Form
│  │ │ ├─ Form.jsx
│  │ │ └─ Form.css
│  │ └─ List.jsx
│  └─ UI 
│
└─ screens
  ├─ User
  │ ├─ Form.jsx
  │ └─ List.jsx
  └─ Root.jsx

简要回顾

展示组件和容器组件保存在src/components

按模块/功能对组件进行划分

UI组件放大src/components/UI

保持页面简单,结构和代码最少

通过路由定义组织页面。对于 /user/list 路由地址来说,我们会有一个页面在 /src/screens/User/List.jsx

组件根据其与组件或src的相对路径进行相应命名。 鉴于此,位于src/components/User/List.jsx的组件将被命名为UserList。 位于src/screens/User/List的组件将命名为ScreensUserList

组件和目录同名时,不要在使用组件的时候重复这个名字。考虑这样一个场景,处于 src/components/User/List/List.jsx 位置的组件会被命名为 UserList 而不是 UserListList

你的点赞是我持续分享好东西的动力,欢迎点赞!

欢迎加入前端大家庭,里面会经常分享一些技术资源。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/109936.html

相关文章

  • 构建前端项目

    摘要:解决思路服务器端渲染服务器端和前端公用同一个应用,然后通过构建工具及配置,确定哪些组件需要再服务器端渲染,那些组件需要再客户端渲染。服务器端渲染,由框架与构建工具配合,并依据一定的项目结构和编码方式,共同运行。 分离 为什么需要 前后端分离、web服务器与static服务器分离: 前端与后端耦合 (需求) 自动化、工程化的构建前端的代码 (基础条件) 模块化、组件化,项目共享代码 (...

    mindwind 评论0 收藏0
  • 前端项目文件组织与组件命名

    摘要:组件划分这种的话组件划分的比较清晰。将组件强势得分为类,这种结构上虽然非常清晰,但是在项目开发的过程中你不得不频繁地将组件在跟之间移来移去,降低了开发体验。 缘由 在开发项目的过程中,大家多多少少会对自己项目的目录结构产生疑惑,如何合理地划分模块以及如何合理的命名,这些如果在项目前期的时候没有好好规范好的话,那么后面新进来的人便会按照自己的逻辑又重新在划分自己的目录,这样日复一日项目体...

    cgh1999520 评论0 收藏0
  • 精益 React 学习指南 (Lean React)- 4.1 react 代码规范

    书籍完整目录 4.1 react 代码规范 showImg(https://segmentfault.com/img/bVyE9m); 关于 基础规范 组件结构 命名规范 jsx 书写规范 eslint-plugin-react 关于 在代码的设计上,每个团队可能都有一定的代码规范和模式,好的代码规范能够提高代码的可读性便于协作沟通,好的模式能够上层设计上避免不必要的 bug 出现。本节会参考...

    zhangqh 评论0 收藏0
  • 前端每周清单第 48 期:Slack Webpack 构建优化,CSS 命名规范与用户追踪,Vue.

    摘要:发布是由团队开源的,操作接口库,已成为事实上的浏览器操作标准。本周正式发布,为我们带来了,,支持自定义头部与脚部,支持增强,兼容原生协议等特性变化。新特性介绍日前发布了大版本更新,引入了一系列的新特性与提升,本文即是对这些变化进行深入解读。 showImg(https://segmentfault.com/img/remote/1460000012940044); 前端每周清单专注前端...

    sean 评论0 收藏0
  • javascript项目开发规范实例

    摘要:首次发表在个人博客总结一下个人在开发及同事代码的过程中遇到的因为一些项目规范带来的问题及认为比较好的解决方法由于个人经验和认知水平有限下面仅代表我的个人观念欢迎各位大佬多给我提建议以本人最近写的一个项目技术栈为为例的使用因为一个项目往 showImg(http://upload-images.jianshu.io/upload_images/3297464-ccdb78e5d7d158...

    sorra 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<