是否有基于React的项目的官方样式指南或命名约定? [英] Is there an official style guide or naming convention for React based projects?

查看:52
本文介绍了是否有基于React的项目的官方样式指南或命名约定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm setting up a React project with my team that will use mobX as state manager, plus TypeScript.

我已经在React项目中看到了常见的模式和命名模式:

I've seen a common pattern in the casing and naming patterns in React Projects:

  1. 非反应文件夹和文件:camelCasekebab-case
  2. 反应(在components文件夹内):PascalCase
  1. Non-React Folders and Files: camelCase or kebab-case
  2. React (inside components folder): PascalCase

react中是否有用于文件夹/文件命名的正式约定?如果没有,是否有基于该模式的样式指南?还是为什么大多数人都使用这个原因?

Is there a formal convention for folder/file naming in react? If not, is there a style guide on which this pattern is based? Or a reason why this one is used most of the times?

推荐答案

只需加上我的两分钱.正如其他人所说,文件结构是不受限制的.但是,组件命名不是.他们应该PascalCase,以便React知道您是否使用functionclassHTMLelement†.

Just to add my two cents. As others have stated, file structure is unopinionated. However, component naming is not. They should be PascalCase for React to know whether or not you're using a function, class or an HTMLelement†.

例如:

class input extends Component {...}

!为什么?因为React不知道您是要使用input元素还是基于类的组件.

Bad! Why? Because React doesn't know whether or not you're trying to use the input element or the class-based component.

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

That's why you'll see PascalCase components:

class Input extends Component {...}

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

† There is one exception, where you can use dot notation. For example, if you had multiple exports and you import them all as fields, then you could do something like:

component/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}
    />
  );
}

components/App/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的结构的开发人员感到困惑.另外,我不喜欢将多个组件堆叠在一个文件中,然后将它们作为一堆导入.此外,该文件可能会变得很大且导航和调试很麻烦(请参见下文中的更多内容).

As a general rule of thumb, I avoid dot notation altogether. It feels clumsy and may confuse other developers who don't know how fields is structured. Plus, I'm not a fan of stacking multiple components within 1 file and then importing them as a bunch. In addition, the file can become quite large and cumbersome to navigate and debug (more on this below).

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

That said, to keep my structure simple, I like to keep main directories lowercase:

├── 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我的组件来表示类似这样的内容:

Then within the component folder, I'll PascalCase my components to represent something like this:

└── 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"包含所有必需的代码.)
  • Reusable components that can be used wherever and whenever.
  • Everything that is related to Input is self-contained within this folder. Therefore, I can hand it off to someone and they can slot it in their application and just use it.
  • Webpack has been set up to automatically import index.js, so it's very easy to import without traversing a ton of nested files: import Input from 'components/Input'; (also, no need to specify the exact js file to use since "index.js" contains all required code).

缺点:

  • 您将有很多小文件夹.
  • 编译错误将全部包含index.js命名法,因此一开始可能会混淆哪些"index.js"失败.
  • You'll have a lot of small folders.
  • Compilation errors will all contain the index.js nomenclature so it can be a bit confusing at first as to what "index.js" has failed.

我过去常做的另一种方法是:

Another approach I used to do was:

└── 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相关的所有事情都包含在此文件夹中. 因此,我可以将其交给某人,他们可以将其放入其应用程序中并使用它.
  • 取决于主文件夹,它描述了组件是function还是class.
  • 发生编译错误时,我确切知道是哪个文件导致了错误.
  • Reusable components that can be used wherever and whenever.
  • Everything that is related to Input is self-contained within this folder. Therefore, I can hand it off to someone and they can slot it in their application and just use it.
  • Dependent on the main folder, it delineates whether the component is a function or a class.
  • When a compilation error occurs, I know exactly which file caused the error.

缺点:

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

其他一般准则:

  • 避免默认导出匿名函数:

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

Example of a default exported anonymous function:

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

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

Why? Because when testing, the function will show up in enzyme as:

<_default />

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

When you have multiple anonymous functions within a component, which one is which!?

<_default />
<_default />
<_default />

  • 避免冗长的文件(不超过150行),因为这会导致阅读/理解以及调试的麻烦.
    • Avoid lengthy files (150 lines or less) as it becomes a pain to read/understand and even more of a pain to debug.
    • 通常,我发现大多数组件在经过适当优化后会落在100行以下.最坏的情况是我将不得不创建小的子组件来补充主组件.但!更容易阅读和调试.

      More often than not, I've found that most components will fall under 100 lines or so when properly optimized. Worst case scenario is I'll have to create small subcomponents to supplement the main component. But! Much easier to read and debug.

      什么更容易阅读:

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

      Example #1 (34 lines with supplemental child components)

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

      Example #2 (318 lines of everything)

      示例1模仿读书.粘贴在一起的多个页面可提供易于阅读的体验.与示例#2相比,它读起来像一英里长的滚动条,很容易迷路!

      Example #1 mimics reading a book. Multiple pages that when glued together create an easy-to-read experience. Versus Example #2 which reads a like a mile-long scroll that can be easy to get lost in!

      • 样式表可以是蛇形或驼峰式.

      这可能会造成混淆,但是这完全取决于您如何应用样式.如果您只是这样导入样式:

      This one can be confusing, but it all depends on how you're applying styles. If you're just importing the style like so:

      import "./styles.css";
      

      然后您可以使用蛇形保护套:

      Then you can use snake-case:

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

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

      However, if you're using css modules, then you'll need to use camelCase:

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

      为什么?因为捆绑器(如Webpack)不支持蛇形导入:

      Why? Because bundlers (like Webpack) don't support snake-case imports:

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


      结论:创建文件夹结构的方法有很多种,其中有一些提示和技巧来保持逻辑流程.只要选择一个最适合您并且不会干扰在您身边工作的人!


      Conclusion: There are many ways to create a folder structure with a few tips and tricks to maintain a logical flow. Just pick one that works best for you AND doesn't interfere with the person working beside you!

      换句话说,K.I.S.S ===保持简单,愚蠢!"

      这篇关于是否有基于React的项目的官方样式指南或命名约定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆