规范开发

129 阅读6分钟

JAVASCRIPT 开发规范

1. 对象

  • 使用直接量创建对象

    // bad
    const item = new Object()
    // good
    const item = {}
    
  • 不要使用保留字作为键名

    // bad
    const userInfo = {
        class: '1',
        privated: true
    }
    // good
    const userInfo = {
        type: '1'
    }
    

2. 数组

  • 使用直接量创建数组

    // bad
    const item = new Array()
    // good
    const item = []
    
  • 向数组增加元素时使用push

    // bad
    const item = []
    item[item.length] = 'Explosion'
    // good
    item.push('Explosion')
    
  • 需要拷贝浅数组的时候使用slice

    const len = items.length;
    const itemsCopy = [];
    const i;
    
    // bad
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    // good
    itemsCopy = items.slice();
    

3. 字符串

  • 使用单引号''包裹字符串

    // bad
    let name = "yueyun"
    // good
    let name = 'yueyun'
    
  • 超过 100 个字符的字符串应该使用连接符写成多行

    // bad
    const errorMessage = 'This is a super long error that was thrown because \
    of Batman. When you stop to think about how Batman had anything to do \
    with this, you would get nowhere \
    fast.';
    
    // good
    const errorMessage = 'This is a super long error that was thrown because ' +
      'of Batman. When you stop to think about how Batman had anything to do ' +
      'with this, you would get nowhere fast.';
    

4. 函数

  • 函数表达式

    // 匿名函数表达式
    var anonymous = function() {
      return true;
    };
    
    // const test = () => {
    	return true
    }
    
    // 命名函数表达式
    var named = function named() {
      return true;
    };
    
    // 立即调用的函数表达式(IIFE)
    (function () {
      console.log('Welcome to the Internet. Please follow me.');
    }());
    
  • 不要再一个代码块中(if while 等)中去声明函数

    // bad
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }
    
    // good
    var test;
    if (currentUser) {
      test = function test() {
        console.log('Yup.');
      };
    }
    
  • 不要将参数命令为arguments 因为这个函数内置的关键字对象

    // bad
    function nope(name, options, arguments) {
      // ...stuff...
    }
    
    // good
    function yup(name, options, args) {
      // ...stuff...
    }
    

5. 属性

  • 使用 . 来访问对象的属性

    const luke = {
      jedi: true,
      age: 28
    };
    
    // bad
    const isJedi = luke['jedi'];
    
    // good
    const isJedi = luke.jedi;
    
  • 当通过变量访问属性时使用中括号 []

    var luke = {
      jedi: true,
      age: 28
    };
    
    function getProp(prop) {
      return luke[prop];
    }
    
    var isJedi = getProp('jedi');
    

6. 变量

  • 优先使用constlet 去声明

    // bad
    var name = 'yueyun'
    // good
    let name = 'yueyun'
    
  • 在作用域顶部声明变量。这将帮你避免变量声明提升相关的问题。

    // bad
    function () {
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      const name = getName();
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // good
    function () {
      const name = getName();
    
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // bad - 不必要的函数调用
    function () {
      const name = getName();
    
      if (!arguments.length) {
        return false;
      }
    
      this.setFirstName(name);
    
      return true;
    }
    
    // good
    function () {
      const name;
    
      if (!arguments.length) {
        return false;
      }
    
      name = getName();
      this.setFirstName(name);
    
      return true;
    }
    

React开发规范

1. 基本规则

  • 一个文件声明一个组件:尽管可以在一个文件中声明多个 React 组件,但是最好不要这样做;推荐一个文件声明一个 React 组件,并只导出一个组件;
  • 使用JSX表达式:不要使用React.createElement的写法
  • React 18尽量使用函数组件

2.命名规范

  • 扩展名:用.jsx || .tsx作为组件的扩展名

  • 文件名:用大驼峰作为文件名,如:ReservationCard.tsx

  • 命名参数:React组件用大驼峰,组件实例用小驼峰

    // bad
    import reservationCard from './ReservationCard';
    
    // good
    import ReservationCard from './ReservationCard';
    
    // bad
    const ReservationItem = <ReservationCard />;
    
    // good
    const reservationItem = <ReservationCard />;
    
  • 组件命名:文件名作为组件名。例如:ReservationCard.jsx应该用ReservationCard 作为参数名。然而,对于一个文件夹里的跟组件,应该用index.jsx作为文件名,同时用文件夹作为组件名

    // bad
    import Footer from './Footer/Footer'
    // bad
    import Footer from './Footer/index'
    // good
    import Footer from './Footer'
    
  • Props命名:避免用 DOM 组件的属性名表达不同的意义

    // bad
    <MyComponent style="fancy" />
    
    // bad
    <MyComponent className="fancy" />
    
    // good
    <MyComponent variant="fancy" />
    

3.对齐

JSX 语法使用这些对齐风格。

// Foo 里面的标签正常缩进
<Foo
  superLongParam="bar"
  anotherSuperLongParam="baz"
>
  <Quux />
</Foo>

// bad
{showButton &&
  <Button />
}

// bad
{
  showButton &&
    <Button />
}

// good
{showButton && (
  <Button />
)}

// good
{showButton && <Button />}

4.引用

JSX 属性中用双引号("),但是在js里用单引号(') Why? 正常的 HTML 属性也通常使用双引号而不是单引号,所以 JSX 属性也使用这个约定。

// bad
<Foo bar='bar' />

// good
<Foo bar="bar" />

// bad
<Foo style={{ left: "20px" }} />

// good
<Foo style={{ left: '20px' }} />

5.属性

props 用小驼峰

// bad
<Foo
  UserName="hello"
  phone_number={12345678}
/>

// good
<Foo
  userName="hello"
  phoneNumber={12345678}
/>

如果 prop 的值是 true 可以忽略这个值,直接写 prop 名就可以。

// bad
<Foo
  hidden={true}
/>

// good
<Foo
  hidden
/>

// good
<Foo hidden />

避免用数组下标作为 key 属性,推荐用稳定的 ID Why? 不使用稳定杆的 ID is an anti-pattern 会对组件性能产生消极影响,并且组件状态容易出现问题。 如果数组元素可能会发生变化,我们不推荐使用下标作为key。

// bad
{todos.map((todo, index) =>
  <Todo
    {...todo}
    key={index}
  />
)}

// good
{todos.map(todo => (
  <Todo
    {...todo}
    key={todo.id}
  />
))}

6. 关于Refs请勿过度使用

7. Hook规则

只在最顶层使用 Hook

不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。(如果你对此感到好奇,我们在下面会有更深入的解释。)

只在 React 函数中调用 Hook

不要在普通的 JavaScript 函数中调用 Hook。你可以:

✅ 在 React 的函数组件中调用 Hook

✅ 在自定义 Hook 中调用其他 Hook

遵循此规则,确保组件的状态逻辑在代码中清晰可见。

8.状态管理规范

约定:

  1. 当我们项目中复杂程度较低时,建议只用state就可以了
  2. 如果仅仅因为存在多层传递数据的场景,不建议使用mobx或redux,可使用context解决
  3. 如果仅仅因为夸路由数据共享,不建议使用mobx或redux,可使用context或者路由传参解决
  4. 如果业务复杂,需要使用第三方状态管理解决复杂度,看下一条
  5. 当项目复杂度一般,小规模团队或开发周期较短、要求快速上线时,推荐使用mobx
  6. 当项目复杂度较高,团队规模较大或要求对事件分发处理可监控可回溯时,推荐使用redux,可尝试使用 rematch或@reduxjs/toolkit,减少模板代码
  7. 如果后端数据符合REST风格且数据格式统一且重复数据较多,推荐使用扁平化处理数据。

9.目录结构

├─package-lock.json
├─package.json ------------ // 项目配置
├─postcss.config.js ------- // postcss 配置
├─public ------------------ // 公开目录
│ ├─favicon.ico
│ └─index.html
├─README.md ---------- // 项目说明
└─src --------------------- // 源码目录
├─App.tsx --------------- // 根组件
├─assets ---------------- // 静态资源目录
│ └─images -------------- // 图片目录
│     └─logo.png ------ // logo 图片
│ └─svg -------------- // 图标目录
│     └─logo.svg ------ // logo 图片
├─components ------------ // 公共组件目录
│ └─Menu ---------------- // 公共组件
│   ├─index.tsx ---------- // 组件文件
│   └─index.scss ------ // 组件样式
├─constants ---------------- // 项目常量
│ └─index.ts
├─libs ------------------ // 第三方库目录
├─index.tsx --------------- // 主入口
├─router ---------------- // 路由配置
│ └─index.tsx
├─store ----------------- // 状态管理
│ ├─module.ts // 模块
│ └─index.ts // 入口
├─tests ----------------- // 测试目录
├─utils ----------------- // 工具目录
│ ├─a.ts
│ └─index.ts
└─pages ----------------- // 视图目录
  └─Home ---------------- // 页面组件
    ├─components -------- // 子组件目录
    │ └─Header
    │   ├─index.tsx
    │   └─index.scss
    └─index.tsx ---------- // 组件主体

10.一切尽量遵循官方文档