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

标签 javascript reactjs naming-conventions

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

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

  • 非 React 文件夹和文件:camelCasekebab-case
  • react (在 components 文件夹内):PascalCase

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

    最佳答案

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

    例如:

    class input extends Component {...}
    

    !为什么?因为 React 不知道您是否尝试使用 input元素或基于类的组件。

    这就是为什么您会看到 PascalCase 组件的原因:
    class Input extends Component {...}
    

    † 有一个异常(exception),您可以使用 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 相关的一切在这个文件夹中是独立的。
    因此,我可以将它交给某人,他们可以将其放入他们的应用程序中并使用它。
  • 取决于主文件夹,它描述了组件是否是 functionclass .
  • 当发生编译错误时,我确切地知道是哪个文件导致了错误。

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


  • 其他一般准则:
  • 避免默认导出匿名函数 :

  • 默认导出匿名函数的示例:
    export default () => (
      <p>Anonymous Function</p>
    );
    

    为什么?因为在测试时,该函数会在 enzyme 中显示为:
    <_default />
    

    当一个组件中有多个匿名函数时,哪个是哪个!?
    <_default />
    <_default />
    <_default />
    
  • 避免冗长的文件(150 行或更少),因为阅读/理解和调试更痛苦。

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

    什么更容易阅读:

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

    Example #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} />
    

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

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

    关于javascript - 是否有基于 React 的项目的官方样式指南或命名约定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55221433/

    相关文章:

    .net - 为什么 .Net 中的常量不是全部大写?

    javascript - ajax jquery更新页面无需刷新

    javascript - 使用 Jest 测试 Typescript,如何测试内部函数?我的导入/导出失败了

    javascript - React JS 中不同组件之间如何共享状态?

    javascript - .click() 在 react 中不起作用

    css - 具有专门组件的 BEM 样式命名

    javascript - 需要从数据库中删除记录并使用jsp中的复选框提醒已删除的id

    javascript - Javascript:在请求的对象“未找到”的情况下,使用模式空对象模式,RORO,未定义等作为Get函数的返回参数

    javascript - array.filter 参数仅在包裹在 {} 周围时才有效

    language-agnostic - 您使用的最常见的方法/变量/类名称是什么?