我正在和我的团队建立一个React项目,该项目将使用mobX作为状态管理器,外加TypeScript
我在React项目的外壳和命名模式中看到了一种常见模式:
- 非反应文件夹和文件:
camelCase或kebab-case - 反应(在
components文件夹中):PascalCase
react中是否有文件夹/文件命名的正式约定?如果没有,是否有此模式所基于的样式指南?或者这是为什么大多数时候都会用到的原因
再加上我的两分钱。正如其他人所说,文件结构是非索引的。但是,组件命名不是必需的。它们应该是PascalCase,以便作出反应以了解您是否在使用函数、类或HTMLelement†
例如:
类输入扩展组件{…}
坏的!为什么?因为React不知道您是在尝试使用input元素还是基于类的组件
这就是您将看到PascalCase组件的原因:
类输入扩展组件{…}
†有一个例外,您可以使用点表示法。例如,如果您有多个导出,并将它们全部作为字段导入,则可以执行以下操作:
组件/字段/索引.js
导入React,{Component}来自“React”;
导出类输入扩展组件{
状态={值:'};
handleChange=({target:{value}})=>{
this.setState({value});
};
渲染=()=>(
<;input type=“text”value={this.state.value}onChange={this.handleChange}/>;
);
}
导出类textarea扩展组件{
状态={值:'};
handleChange=({target:{value}})=>{
this.setState({value});
};
渲染=()=>(
<;文本区域
type=“text”
value={this.state.value}
onChange={this.handleChange}
/&燃气轮机;
);
}
组件/App/index.js
导入React,{Fragment}来自“React”;
从“./字段”导入*作为字段;
常量应用=()=>;(
<;碎片>;
<;fields.input/>;
<;fields.textarea/>;
<;碎片>;
);
导出默认应用程序;
作为一般的经验法则,我完全避免使用点符号。它感觉很笨拙,可能会让其他不知道字段是如何构造的开发人员感到困惑。另外,我不喜欢在一个文件中堆叠多个组件,然后将它们作为一堆导入。此外,该文件可能会变得非常大,并且导航和调试起来非常麻烦(下面将对此进行详细介绍)
也就是说,为了保持结构简单,我喜欢将主目录保持小写:
├── dist//要提供的已编译应用程序文件
| ├── css
| | ├── main.[contenthash:8].css
| | └── main.[contenthash:8].css.map
| ├── js
| | ├── main.[hash].js//根据应用程序大小,这可能包含多个用于代码拆分的js文件
| | └── main.[hash].js.map
| ├── 媒体
| | └── [hash].[ext]//字体和图像等静态资产
| └── 图标文件
| └── index.html
|
├── config//支持“webpackdevserver”配置文件
| ├── devServer.js
| ├── envs.js
| ├── optimization.js
| ├── output.js
| ├── path.js
| ├── plugins.js
| └── rules.js
|
├── 平民的
| ├── 图标文件
| └── index.html
|
├── src
| ├── 动作//重复动作
| ├── 组件//只显示“东西”的有状态和无状态可重用组件——有状态组件更改和操作UI
| ├── 容器//利用可重用“组件”来CRUD数据和/或连接到redux的有状态组件
| ├── 图像
| ├── 页面//访问“/路线”时利用组件/容器显示某些内容
| ├── 还原剂//还原剂
| ├── root//aka“<;App/>;”,它将“路由”、redux和其他顶级支持文件组合到一个位置
| ├── 路由//将“页面”分配给“/路由”
| ├── 样式//所有“组件”使用的共享和/或全局样式
| ├── 类型//重复类型
| ├── utils//支持应用程序文件:如测试设置、自定义多边形填充、axios配置等
| └── index.js//一个简单的文件,“ReactDOM.render”是“App”
|
├── server.js//express安装程序为“dist”文件夹提供服务
└── webpack.config.js
然后在component文件夹中,我将调用我的组件来表示如下内容:
└── 组件
└── 输入
├── __测验__
| └── Input.test.js//“index.js”的jest单元测试
├── index.js//要导出的所有必需代码/样式
└── styles.scss//“index.js”所需的样式
为什么是这种结构?
- 可重用组件,可随时随地使用
- 与
输入相关的所有内容都包含在此文件夹中。
因此,我可以把它交给别人,他们可以把它放在自己的应用程序中使用 - Webpack已设置为自动导入
index.js,因此导入非常容易,无需遍历大量嵌套文件:从“组件/输入”导入输入(另外,无需指定要使用的确切的js文件,因为“index.js”包含所有必需的代码)
缺点:
- 你会有很多小文件夹
- 编译错误都将包含
index.js术语,因此一开始可能会有点混淆什么“index.js”失败了
我曾经采用的另一种方法是:
└── 组件
├── 输入//小写名称来描述它是一个“纯”函数——实际函数将是一个PASCALCASE“输入”
| ├── input.test.js//“input.js”的jest单元测试
| ├── input.js//要导出的所有必需代码/样式
| └── styles.scss//“input.js”所需的样式
|
└── 侧边栏//因为它是一个“类”
├── Sidebar.test.js//“Sidebar.js”的jest单元测试
├── Sidebar.js//要导出的所有必需代码/样式
└── styles.scss//“Sidebar.js”所需的样式
为什么是这种结构?
- 可重用组件,可随时随地使用
- 与
输入相关的所有内容都包含在此文件夹中。
因此,我可以把它交给别人,他们可以把它放在自己的应用程序中使用 - 根据主文件夹,它描述组件是
函数还是类 - 当发生编译错误时,我确切地知道是哪个文件导致了错误
缺点:
- 你会有很多小文件夹
- 有时组件可能会从有状态更改为无状态(反之亦然),因此如果您严格遵守此命名模式,则必须更新主文件夹以反映更改,这意味着您还需要更新使用此组件的任何其他文件的路径
- 导入看起来有点冗余和冗长:
import Input from'components/Input/Input.js'
其他一般准则:
- 避免默认导出匿名函数:
默认导出的匿名函数示例:
导出默认值()=>;(
<;p>;匿名函数<;/p>;
);
为什么??因为测试时,该功能将在酶中显示为:
<_默认值/>;
当一个组件中有多个匿名函数时,哪个是哪个
<_默认值/>;
<_默认值/>;
<_默认值/>;
- 避免使用冗长的文件(150行或更少),因为阅读/理解这些文件会让人感到痛苦,调试时更痛苦。
通常情况下,我发现大多数组件在经过适当优化后都会在100行左右。最坏的情况是我必须创建小的子组件来补充主组件。但是更易于阅读和调试
更容易阅读的内容:
示例#1(带有补充子组件的34行)
示例2(共318行)
示例1模仿看书。多页,当粘在一起时,创建一个易于阅读的体验。而第二个例子读起来像一英里长的卷轴,很容易迷路
- 样式表可以是蛇壳或骆驼壳。
这可能会让人困惑,但这完全取决于您如何应用样式。如果只是像这样导入样式:
导入“/styles.css”;
然后您可以使用snake case:
<;输入className=“snake case”type=“text”value=”“onChange={this.handleChange}/>;
但是,如果您使用的是css模块,则需要使用camelCase:
从“/styles.css”导入{camelCaseClassName};
为什么??因为绑定器(如Webpack)不支持snake case导入:
<;输入className={camelCaseClassName}type=“text”value=”“onChange={this.handleChange}/>;
结论:创建文件夹结构有很多方法,其中包括一些技巧和技巧,以保持逻辑流。只需选择一个最适合你且不会干扰你身边工作的人
<