likes
comments
collection
share

【精简|译】供参考的 React 代码编写规范

作者站长头像
站长
· 阅读数 2

【精简|译】供参考的 React 代码编写规范

原文: React Coding Standards And Practices To Level Up Your Code 作者 Jon Jones

可译为:《React 代码编写标准与实践:提升你的代码水平》

Pre. 名词释义

  • 帕斯卡命名法(PascalCase),指每个单词的首字母都大写、通过单词首字母的大小写来分隔单词的命名方法。 e.g HeadComponent UserInfos

  • 驼峰命名法(camelCase),指首字母小写、其余单词首字母大写分隔单词的命名方法。

  • 守卫模式(Guard Clause),一种编程模式,指及在函数的开始处添加一系列的条件检查。如果任何一个检查失败,函数将立即返回或抛出异常,而不是继续执行后续的代码。 e.g.

    function divide(a, b) {
      // 守卫条件:确保除数不为0
      if (b === 0) {
        throw new Error('Cannot divide by zero.');
      }
    
      // 如果守卫条件都通过,则执行除法操作
      return a / b;
    }
    
    function foo(bar){
        if(foo === null){
            throw new Errow('foo cannot be null')
        }
        if(foo === undefined){
            // 通常也可能会搭配 return 使用
            console.alert('foo cannot be undefined')
            return
        }
    }
    
  • 纯函数(pure function):指传入相同输入,永远会返回对应的同一结果,同时不会对外部状态进行修改的函数。 e.g. (a)=>a+1 是纯函数,(a)=>{console.log(a);return a + 1} 不是纯函数。

1.0 命名约定 Name Convention

组件文件名应使用帕斯卡命名法书写:

  • Header.js
  • HeroBanner.js
  • CookieBanner.js
  • BlogListing.js

非组件文件名应使用驼峰命名法书写:

  • myUtilityFile.js
  • cookieHelper.js
  • fetchApi.js

单元测试文件应与其对应的文件使用相同的名称,并在之后以 .test 进行标识:

  • CookieBanner.js
  • CookieBanner.test.js
  • fetchData.js
  • fetchData.test.js

属性名称应使用驼峰命名法

  • className
  • onClick

内联样式应使用驼峰命名法

<div style={{fontSize:'1rem'}}></div>

变量名称应使用驼峰命名法。变量名称可以包含数字和特殊字符:

const variable = 'test';
let variableBoolean = true;

CSS文件应与组件使用相同的名称

  • CookieBanner.css
  • Header.css

如果一个组件需要多个文件(如css、测试文件),请将所有文件放在组件的文件夹内。e.g.

-- MyComponent
|- MyComponent.tsx
|- myComponentUtils.ts
|_ caculators.js

对于React组件,请使用.jsx或.tsx文件扩展名。

2.0 可能能帮助你避免 Bug 的代码编写措施 BUG AVOIDANCE

  • 使用可选链:当某个对象可能为nullundefined时,使用可选链(optional chaining)操作符?.来安全地访问其属性,以避免运行时错误。

  • 使用守卫模式/prop-types库/TypeScript:为了确保传递的参数有效,使用守卫模式(guard pattern)、prop-types库或者TypeScript的类型系统来验证传入的参数。

    注:prop-types 库是用于在 React 应用程序中为组件的属性(props)定义类型的库,适用于JavaScript下的 react 开发。如果你使用 TypeScript,可以无视这一点。

  • 创建纯函数:尽量编写纯函数(PURE functions),这些函数应该只依赖于输入的参数,并避免产生副作用(side-effects),即不改变外部状态或数据。

  • 避免在处理数组时改变状态:在操作数组时,尽量不要改变数组本身的状态。可以使用不可变数据结构或者创建数组的副本来进行修改。

  • 移除所有的console.log() :在开发完成后,确保从代码中移除所有的console.log()语句,因为这些调试输出可能会泄露信息,影响性能,或在生产环境中造成干扰。

    注:在开发时,可以考虑使用 console.group 等输出函数更好地打印调试信息。

  • 将props视为只读:对待组件的props时要像对待只读数据一样,不要尝试去修改它们。如果需要改变props的值,应该创建一个副本或者使用状态来管理这些变化。

3.0 代码架构与精简代码 ARCHITECTURE & CLEAN CODE

  • 不要违反 Don't Repear Yourself 的代码编写规则:不要重复编写代码,创建工具代码文件(e.g. utils.js)以避免重复编写代码。

    注:原文是 Create utility files to avoid duplicate code ,所谓 utility files ,我想应该是指那些将可复用的功能函数抽离到一个代码文件中,以供在不同地方导入复用。大多数情况下这类文件命名为 utils.js / utils.tsx

  • 遵循组件/展示模式:在适当的地方遵循组件和表现层模式,组件应该遵循单一职责原则。

    组件/展示模式 (component/presentation pattern)

  • 适当使用高阶组件:在适当的情况下使用高阶组件(Higher Order Components)。

    高阶组件在我个人看来就是高阶函数,只能说 React 是真的喜欢用函数式编程里的概念啊。简单来讲,便是

  • 将代码分割到相应的文件中:将JavaScript、测试和CSS代码分别存放在不同的文件中。

  • 在每个文件夹中创建index.js以便于导出,这样做可以减少导入时的重复命名。

    // 导入
    import { Nav } from './Nav';
    import { CookieBanner } from './CookieBanner';
    
    // 导出
    export { Nav, CookieBanner };
    
  • 每个文件只包含一个React组件:每个文件应该只定义一个React组件。

  • 倾向于使用无状态组件:尽可能使用无状态组件(functionless components)。

  • 不要使用混入(mixins) :避免使用React的混入特性,因为它可能导致代码结构复杂和不可预测。

  • 避免不必要的注释:只添加有意义的注释,不必要的注释应该被删除。

  • 重构过长的函数:如果某个方法的长度超过了屏幕宽度,应该将其重构为更小的单元。

  • 删除注释掉的代码:不应该提交注释掉的代码到版本控制系统,而应该将其删除,保持代码的整洁。

4.0 在使用ES6标准编写代码时,你可以考虑的问题:

  • 可以使用展开运算符(spread operator)来简化代码吗?

    使用展开运算符(...)在处理数组和对象时可以用来简化代码。因此可以多多考虑使用它。

  • 可以使用解构赋值(destructuring)吗?

    解构赋值能够从数组或对象中提取数据并直接赋值给变量,这样可以减少访问对象属性或数组元素时的样板代码。

  • 只使用letconst

  • 倾向于使用箭头函数(arrow functions)

  • 对于某些样板代码,可以使用展开运算符代替吗?

  • 可以使用可选链运算符(optional chain operator)代替显式空值检查吗?

  • 可以使用空值合并运算符(nullish coalescing operator)代替显式的空值比较吗?

    空位合并运算符(??)用于在左侧的值为nullundefined时,返回右侧的值。这可以简化条件语句中的空值检查和默认值赋值。

    e.g.

    // from mdn: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing
    const foo = null ?? 'default string';
    console.log(foo);
    // Expected output: "default string"
    
    const baz = 0 ?? 42;
    console.log(baz);
    // Expected output: 0
    

5.0 测试 TESTING

有点遗憾的是,我没怎么做过测试,因此不保证这里的一些翻译理解是正确的。

  • 编写测试:你应当为你的代码编写单元测试,以确保每个功能模块都能按预期工作。

  • 使用Coveralls定义质量门限 (quality gate)

    Coveralls 是用于监测代码仓库中的测试覆盖率的在线服务。我没用过,不太清楚国内能不能用orz

  • 不要在一个测试中测试多于一件事:每个测试应该只关注一个特定的功能或行为,这样可以确保测试的清晰性和可维护性。当发现问题时,也更容易定位到具体的代码段。
  • 测试代码中不应存在逻辑:测试代码应该尽可能简单直接,避免包含复杂的逻辑。这样可以减少测试代码的维护成本,并确保测试的稳定性和准确性。
  • 测试类 ( test classes )应该只测试一个类:当你为一个类编写测试时,确保这些测试专注于这个类的行为。不要尝试在一个类的测试中混入其他类的行为测试,这样可以提高测试的针对性和清晰度。
  • 应当模拟需要与网络或数据库通信的代码:在进行单元测试时,应当模拟那些需要与外部系统(如网络或数据库)交互的代码。这样可以确保测试的独立性和可控性,避免外部因素影响测试结果。

6.0 CSS 规范

  • 避免使用内联CSS (inline CSS) 。尽量避免在 HTML 元素上直接写 CSS。 e.g.

    <!-- 使用内联CSS设置样式 -->
        <div style="color: blue; font-size: 20px; text-align: center;">
            Applied Inline CSS
        </div>
    
  • 遵循团队的命名约定(例如 BEM、SUIT 等)。

    BEM规范:getbem.com/introductio…

    SUIT规范:github.com/suitcss/sui…


    最后更新时间:2024-04-02