React作为一个库,它没有划定项目的团体构造。这很好,因为它给了我们自在去尝试差别的要领,并顺应更适合我们的体式格局。另一方面,这可以会给React范畴的开发人员带来一些疑心。我
React 作为一个库,它没有划定项目的团体构造。这很好,因为它给了我们自在去尝试差别的要领,并顺应更适合我们的体式格局。另一方面,这可以会给React范畴的开发人员带来一些疑心。
我将会在本文为人人展现我已运用过一段时间而且结果不错的体式格局,这些体式格局没有经由过程重新造轮子来完成,而是经由过程将社区中的计划组合和提炼获得。
想浏览更多优良文章请猛戳GitHub博客,一年百来篇优良文章等着你!
目次构造
我常常碰到的一个题目是怎样构造文件和目次构造。在这篇文章中,我们以为你已有一个最小的构造,就像用 create-react-app
竖立的构造一样。
create-react-app
为我们天生了一个基本的项目,包含根目次另有诸如.gitignore
, package.json
, README.md
, yarn.lock
的文件。
它还天生 public
和src
目次, src
目次是我们保存源代码的处所。
请看下面的图片,以及形貌的构造:
在这篇文章中,我们只关注src
目次,src 之外坚持稳定。
容器和组件 (Containers and Components)
你可以已在某些项目的根目次下看到了容器和展现组件之间的星散。我的意义是,在src
中,在 src 目次下有 containers
目次和 components
目次:
src
├─ components
└─ containers
然则,这类要领有一些题目,以下所示:
- 主观的划定规矩:关于容器和展现组件,没有明白的划定规矩。彼此之间的差别多是主观的,当你在一个团队中时,很难让一切开发人员赞同并评判这个题目。
- 它没有斟酌组件的动态性:纵然当你决议某个组件适合于某个特定范例时,也很轻易在项目生命周期中对其举行变动,使其从另一种范例变成另一种范例,终究迫使你把它从
components
挪到 containers
目次下,反之亦然。 - 许可两个具有雷同称号的组件:组件的定名在运用程序中具有声明性和唯一性,以防止殽杂每一个组件的职责。然则,上面的体式格局破坏了具有雷同称号的两个组件,一个是容器,另一个是展现示组件。
- 效力低下: 纵然你在完成一个自力特征时,也不得不常常在
containers
和 components
目次下往返切换,因为一个自力特征有两种差别范例的组件是再一般不过的事变了。
另有一种要领,在模块内部保存containers
和components
星散:
src
└─ User
├─ components
└─ containers
上述要领最大限制地减少了在项目树中差别层级目次切换的题目。但是,它会增添许多噪音。依据你的运用程序有若干模块,你终究会竖立几十个containers
和components
目次。
出于这些缘由,当我们议论构造目次和文件时,经由过程展现与容器的观点来拆分组件是可有可无的。 也就是说,除页面外,我们将把一切组件放在 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
。
你的点赞是我延续分享好东西的动力,迎接点赞!
迎接到场前端人人庭,内里会常常分享一些手艺资本。