是否有基于 React 的项目的官方样式指南或命名约定?

IT技术 javascript reactjs naming-conventions
2021-03-27 23:56:46

我正在与我的团队建立一个 React 项目,该项目将使用 mobX 作为状态管理器,以及 TypeScript。

我在 React 项目中的大小写和命名模式中看到了一个常见的模式:

  1. 非 React 文件夹和文件:camelCasekebab-case
  2. react(components文件夹内):PascalCase

react中是否有文件夹/文件命名的正式约定?如果没有,是否有此模式所基于的风格指南?或者大多数时候使用这个的原因?

5个回答

只是为了加上我的两分钱。正如其他人所说,文件结构是不受约束的。但是,组件命名不是。他们应该PascalCase为应对知道你是否正在使用functionclassHTMLelement†。

例如:

class input extends Component {...}

不好为什么?因为 React 不知道你是在尝试使用input元素还是基于类的组件。

这就是为什么您会看到 PascalCase 组件的原因:

class Input extends Component {...}

† 有一个例外,您可以在其中使用dot notation. 例如,如果您有多个导出并将它们全部导入为fields,那么您可以执行以下操作:

组件/字段/index.js

import React, { Component } from 'react';

export class input extends Component {
  state = { value: "" };

  handleChange = ({ target: { value } }) => {
    this.setState({ value });
  };

  render = () => (
    <input type="text" value={this.state.value} onChange={this.handleChange} />
  );
}

export class textarea extends Component {
  state = { value: "" };

  handleChange = ({ target: { value } }) => {
    this.setState({ value });
  };

  render = () => (
    <textarea
      type="text"
      value={this.state.value}
      onChange={this.handleChange}
    />
  );
}

组件/应用程序/index.js

import React, { Fragment } from 'react';
import * as fields from "../fields";

const App = () => (
  <Fragment>
     <fields.input />
     <fields.textarea />
   <Fragment>
);

export default App;

作为一般经验法则,我dot notation完全避免感觉很笨拙,可能会让其他不知道如何fields构建的开发人员感到困惑另外,我不喜欢在一个文件中堆叠多个组件,然后将它们作为一堆导入。此外,该文件可能会变得非常大且难以导航和调试(更多内容见下文)。


也就是说,为了保持结构简单,我喜欢将主目录保持小写:

├── dist // compiled application files to be served
|   ├── css
|   |   ├── main.[contenthash:8].css
|   |   └── main.[contenthash:8].css.map
|   ├── js
|   |   ├── main.[hash].js // depending on app size, this may contain multiple js files for code splitting
|   |   └── main.[hash].js.map
|   ├── media
|   |   └── [hash].[ext] // static assets like fonts and images
|   └── favicon.ico
|   └── index.html
|
├── config // supporting "webpackdevserver" configuration files
|   ├── devServer.js
|   ├── envs.js
|   ├── optimization.js
|   ├── output.js
|   ├── paths.js
|   ├── plugins.js
|   └── rules.js
|
├── public
|   ├── favicon.ico
|   └── index.html
|
├── src
|   ├── actions // redux actions
|   ├── components // stateful and stateless reusable components that just display "stuff" -- stateful components change and manipulate the UI
|   ├── containers // stateful components that utilize the reusable "components" to CRUD data and/or are connected to redux
|   ├── images
|   ├── pages // utilize components/containers to display something when visiting a "/route"
|   ├── reducers // redux reducers
|   ├── root // aka "<App />" that combines "routes", redux and other top-level supporting files into one place
|   ├── routes // assigns "pages" to a "/route"
|   ├── styles // shared and/or global styles used by all "components"
|   ├── types // redux types
|   ├── utils // supporting app files: like test setup, custom polyfills, axios configurations, ...etc
|   └── index.js // a simple file that "ReactDOM.render"s the "App"
|
├── server.js // express setup to serve the "dist" folder
└── webpack.config.js

然后在component文件夹中,我将 PascalCase 我的组件来表示如下内容:

└── components
    └── Input
        ├── __tests__
        |   └── Input.test.js // jest unit tests for "index.js"
        ├── index.js // all required code/styles to be exported
        └── styles.scss // styles required by "index.js"

为什么是这种结构?

  • 可重复使用的组件,可随时随地使用。
  • 与此相关的所有内容都Input包含在此文件夹中。因此,我可以将它交给某人,他们可以将它放入他们的应用程序中并使用它。
  • Webpack 已设置为自动导入index.js,因此无需遍历大量嵌套文件即可轻松导入:(import Input from 'components/Input';此外,无需指定js要使用的确切文件,因为“index.js”包含所有必需的代码)。

缺点:

  • 你会有很多小文件夹。
  • 编译错误都将包含index.js命名法,因此一开始可能会有点混淆“index.js”失败的原因。

我曾经做过的另一种方法是:

└── components
    ├── input // lowercase name to delineate it's a "pure" function -- the actual function will be a PascalCased "Input"
    |   ├── input.test.js // jest unit tests for "input.js"
    |   ├── input.js // all required code/styles to be exported
    |   └── styles.scss // styles required by "input.js"
    |
    └── Sidebar // PascalCase because it's a "class"
        ├── Sidebar.test.js // jest unit tests for "Sidebar.js"
        ├── Sidebar.js // all required code/styles to be exported
        └── styles.scss // styles required by "Sidebar.js"

为什么是这种结构?

  • 可重复使用的组件,可随时随地使用。
  • 与此相关的所有内容都Input包含在此文件夹中。因此,我可以将它交给某人,他们可以将它放入他们的应用程序中并使用它。
  • 根据主文件夹,它描述了组件是 afunction还是class.
  • 当发生编译错误时,我确切地知道是哪个文件导致了错误。

缺点:

  • 你会有很多小文件夹。
  • 有时组件可以从有状态变为无状态(反之亦然),因此如果您严格遵守此命名模式,则必须更新主文件夹以反映更改,这意味着您还需要更新使用此组件的任何其他文件的路径。
  • 导入看起来有点多余和冗长: import Input from 'components/input/input.js';

其他一般准则:

  • 避免默认导出匿名函数

默认导出匿名函数的示例:

export default () => (
  <p>Anonymous Function</p>
);

为什么?因为在测试时,该函数会在酶中显示为:

<_default />

当你在一个组件中有多个匿名函数时,哪个是哪个!?

<_default />
<_default />
<_default />
  • 避免冗长的文件(150 行或更少),因为阅读/理解和调试更痛苦。

通常情况下,我发现大多数组件在适当优化后都会低于 100 行左右。最坏的情况是我必须创建小的子组件来补充主要组件。但!更容易阅读和调试。

什么更容易阅读:

示例 #1(34 行带有补充子组件)

示例 #2(318 行所有内容)

Example #1 模仿阅读一本书。将多个页面粘合在一起可创建易于阅读的体验。与示例 #2 相比,它读起来就像一英里长的卷轴,很容易迷路!

  • 样式表可以是snake-case 或camelCase。

这可能会令人困惑,但这完全取决于您如何应用样式。如果您只是像这样导入样式:

import "./styles.css";

然后你可以使用snake-case:

<input className="snake-case" type="text" value="" onChange={this.handleChange} />

但是,如果您使用的是css modules,则需要使用camelCase:

import { camelCaseClassName } from "./styles.css";

为什么?因为打包器(如 Webpack)不支持蛇案例导入:

<input className={camelCaseClassName} type="text" value="" onChange={this.handleChange} />

结论: 有很多方法可以通过一些提示和技巧来创建文件夹结构,以维护逻辑流程。只需选择最适合您且不会干扰在您身边工作的人!

换句话说,KISS === “保持简单,愚蠢!”

如果说原生,您指的是 HTML 元素,例如divpinput等等,那么是的,您应该elements使用 PascalCase将您的组件与这些元素分开同样,如果一个组件和一个元素共享相同的名称——例如,你有一个命名的类div——那么 React 怎么知道要渲染哪个!?你指的是类还是指的是元素?简而言之,PascalCase 有助于避免这些命名冲突。此外,React 将小写名称视为元素(这也包括驼峰式名称)!
2021-06-05 23:56:46
非常感谢,这对我来说更清楚。只是为了澄清一下,所以在组件名称上使用 PascalCase 的原因是组件的第一个字母不是小写并且与“本机”关键字混淆......就是这样吗?谢谢!
2021-06-21 23:56:46

没有官方指南。大多数项目采用 PascalCase 作为 react 组件的原因是为了模仿该文件的主要导出。React 组件按照惯例是 PascalCased,当使用 jsx 时,pascal 大小写成为强制性的(实际上只有大写的首字母成为强制性的)。其余文件的 cameCase 或 kebab-case 只是遵循一般 javascript 项目更常见的偏好。

React 没有官方的风格指南。但是你可以使用eslintAirBnb最流行的 React 配置。

在这里阅读更多https://github.com/airbnb/javascript/tree/master/react

在许多语言中,PascalCase 它们的类很常见,并且具有驼峰式函数和变量名。一个JS例子,

function hello() {console.log('world')};

class Foo {
  say() { console.log('bar') }
}
let foo = new Foo();
foo.say();

组件通常是类class Nav extends React.PureComponent,因此逻辑连接是类似地命名包含类的文件,从而导致匹配的 case 导入语句import Nav from './Nav

您可能还有一个实用程序文件,它导出一个函数,而不是一个类。同样,有匹配的案例很好import hello from './hello'

因此,您可能会发现一个常见的结构,例如

src
- App.js
- components/
  - Nav.js
- util/
  - hello.js
@Ruid'Orey React 是一个 Facebook 项目。据我所知,他们没有明确的“你必须这样做”的指导方针。但是,如果我们都任由自己的设备,我们可能会弄得一团糟。AirBnB 有一个 styleguide 可能会有所帮助,但具体来说是一个正式的模式?从来没听说过。 github.com/airbnb/javascript/tree/master/react
2021-05-26 23:56:46
谢谢,但我的问题更多的是,如果在 React 中该模式是正式的官方模式......因为大多数 React 项目似乎都使用它而不是其他模式/约定。尽管 React 被认为是没有意见的。并尝试理解 React 中为什么会这样。
2021-06-14 23:56:46

目前我有一个以 PascalCase 命名的文件夹,其中有一个index.js文件 - 这是我的组件。

任何直接附加到根组件的组件我都嵌套在他们自己的文件夹中,并使用他们自己的 index.js。我还使用点符号来描述与该文件夹直接相关的任何文件的性质,例如[descriptor].[name].[prefix]

Components/
    ComponentName/
    |---util.componentName.js
    |---constants.componentName.js
    |---styles.componentName.scss
    |---index.js
        ChildComponent1/
        |---util.childComponent1.js
        |---styles.childComponent1.scss
        |---index.js
        ChildComponent2/
        |---util.childComponent2.js
        |---styles.childComponent2.scss
        |---index.js

对于我的 mobx 商店,因为我的商店module不太可能拥有真正深层的文件夹结构,所以我有一个根module文件夹,其中通常包含两个js文件Actions.jsindex.js索引是我的主要商店类,它扩展了我的 Actions 类。(我发现一个带有observable,computedaction属性的mobx 类有点混乱)。

Store 文件夹本身有一个index.js导入所有同级存储module,以便稍后将它们组合成一个存储对象(我的项目需要)

Store/
    StoreModule/
    |---actions.js
    |---index.js
    AnotherStoreModule/
    |---actions.js
    |---index.js
    index.js

我想没有真正正确的方法,因为它取决于偏好,上面的方法我认为可读,并且在 VSCode 上使用工具查找文件时,它可以更轻松地搜索诸如“我想查看作为常量文件的所有文件”之类的细节"搜索constants.[component name]

我不觉得在文件中保留组件名称是值得的。你也可以搜索ComponentName/styles.js
2021-06-07 23:56:46
@fard 这一切都可以解释,但是当我command P在我的 VS Code 中使用来查找文件名时,我发现将文件名格式化styles.[filename]很有用,特别是因为我目前正在处理的项目是 React-Native 和我们的风格文件是js文件,当我试图找到正确的文件而不是寻找scss后缀时,它让我更清楚
2021-06-11 23:56:46