React学习笔记之一---项目结构

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

目录结构

我们经常会遇到一个问题,那就是如何组织文件和目录的结构。当我们用creat-react-app 为我们生成一个基础的项目时,包含了根目录还有诸如.gitignore,packge.json,REDME.md,yarn.lock的文件。同时它还生成了publick和src目录,src目录是我们保存源代码的地方。
请添加图片描述
其中各个文件的作用不一一赘述,如有不明白可以将它翻译一下,或者去网上搜一下。在此我们只讨论src目录。

容器与组件

你可能已经在某些项目的根目录下看到了容器的展示组件之间的分离。在scr的目录下有containers目录和commpoents目录

src
├─ components 
└─ containers

但是这种方法有一些问题:

  • **主观规则:**对于容器和展示组件,没有明确的规则。彼此之间的差异可能是主观的,当你在一个团队中时,很难让所有开发人员赞成并判断这个问题。
  • **没有考虑组件的动态性:**即使当你决定摸个组件适合于某个特定类型时,很容易在项目生命周期中对其进行更改,使其从一种类型变为另外类型,最终迫使你把它从commponents挪到containaers目录下,反之亦然。
  • **允许两个组件具有相同的名称:**组件的命名在应用程序中具有申明性和唯一性,以避免混淆每个组件的职责。但是上面的范式破坏 了具有相同名称的两个组件,一个是容器,另外一个是展示组件。
  • **效率低下:**即使你在实现一个独立特性时,也不得经常在containers和components分离:
src
└─ User
  ├─ components
  └─ containers

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

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

拆分和组合代码

在commponents目录中,我们按模块/功能对文件进行分组。
在用户的增删改查中,我们只有user模块,结构是这样的。

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

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

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

测试文件和被测试的文件保持一致。在上面的例子中,From.jsx的测试文件会被放在同一个文件夹下并且命名为From.spec.jsx

除了通过模块拆分组件之外,我们还在src/components中包含一个UI目录,以保留其中的所有通用组件。UI组件是通用的组件,不属于模块。它们是可以保留在开源库中的组件,因为它们没有来自特定应用程序的任何业务逻辑。这些组件的示例包括:按钮,输入,复选框,选择,模态框,数据可视化组件等等。

命名规范

上面我们看到了如何构建目录并按照模块分离我们的组件,但是我们该如何命名它们呢?
当我们谈论命名组件时,它涉及我们给类或者定义组件的常量名称:

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

如上所述,我们为组件提供的名称应该在应用程序中清晰且独特,以便容易找到避免可能混淆。当我们需要使用工具作为React Dev工具进行调试时,以及当应用程序中发生运行时错误时,组件的名称非常方便,错误总是与发生错误的组件名称一起出现。

我们采用基于路径的组件命名方式,即根据相对于componentf文件目录的相对路径来命名,如果在此文件夹意外,则使用相对于src目录的路径,举个例子:
组件的路径如果是component/User/List.jsx,那么它就可以被命名为UserList。
当文件维语具有相同名称的组件中时,我们不需要重复该名称。也就是说,component/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';

想象一下名称重复十几次甚至更多的样子。
英雌我们根据文件的的上下文来命名文件,根据组件的相对位置来命名组件是一种更好的方式。

页面

如果要对一个用于做增删改查的操作,我们需要有用户列表页面,创建新用户的页面以及编辑已有用户的页面。我们将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 = () => (
  <Router>
    <Switch>
      <Route path="/user/list" component={ScreensUserList} />
      <Route path="/user/create" component={ScreensUserForm} />
      <Route path="/user/:id" component={ScreensUserForm} />
    </Switch>
  </Router>
);

export default ScreensRoot;

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

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

你可能会注意到所有组价都将screen作为其名称的前缀。当组件位于 Component目录之外的时候,我们应该根据它到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 } }) => (
  <div>
    <h1>
      {`${!params.id ? 'Create' : 'Update'}`} User
    </h1>
    <UserForm id={params.id} />
  </div>
);

export default ScreensUserForm;

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

src
├─ components 
│  ├─ User
│  │ ├─ Form
│  │ │ ├─ Form.jsx
│  │ │ └─ Form.css
│  │ └─ List.jsx
│  └─ UI 
│
└─ screens
  ├─ User
  │ ├─ Form.jsx
  │ └─ List.jsx
  └─ Root.jsx
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值