React组内开发规范

React组内开发规范

下面是我们部门总结的内部开发规范(试行版本),欢迎提意见。

部门FE React 组件开发规范

适用范围

部门FE 所有基于React开发的(包含fcui2)组件,欢迎提意见。

要求

  • 必须:表示绝对要求这样做。
  • 必须不:表示绝对不要求这样做。
  • 应该/建议:表示一般情况下应该这样做,但是在某些特定情况下可以忽视这个要求。
  • 应该不/不建议:表示一般情况下不应该这样做,但是在某些特定情况下可以忽视这个要求。
  • 可以:表示这个要求完全是可选的,你可以这样做,也可以不这样做。

基本概念 [basic-concepts]

  • 实例化生命周期
    • getDefaultProps
    • getInitialState
    • componentWillMount
    • render
    • componentDidMount
  • 更新期生命周期
    • getInitialState
    • componentWillMount
    • render
    • componentDidMount
  • 运行期生命周期
    • componentWillReceiveProps
    • shouldComponentUpdate
    • componentWillUpdate
    • render
    • componentDidUpdate
  • 销毁期生命周期
    • componentWillUnmount

核心依赖 [deps](针对内部UI库)

  • 必须在UI内只依赖React,underscore。
  • 必须不在UI内部任何地方使用jQuery等直接操作DOM的库

JSX书写 [jsx]

参考:Airbnb的style guide

  • 必须命名JSX文件为.jsx.js。
  • 必须使用PascalCase作为文件名。
  • 必须只包含一个React Component在一个JSX文件中。
  • 必须令文件名与所包含的React Component名字相同。
  • 必须只能使用React.createClass()来创建一个React Component。

    虽然ES6 Class和pure function都可以创建React Component,
    但ES6 Class不能使用mixin做扩展,与目前的扩展方法冲突;
    Pure function较难掌握和管理。

  • 必须使用JSX语法来生成组件的DOM片段。

  • 必须不能在JSX中出现React.createElement()
  • 必须遵守下面示例中的DOM片段对齐方式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// bad
<Foo superLongParam="bar"
anotherSuperLongParam="baz" />

// good
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
/>

// if props fit in one line then keep it on the same line
<Foo bar="bar" />

// children get indented normally
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
>
<Quux />
</Foo>

  • 必须在DOM片段中使用双引号"

    Why?JSX attributes can’t contain escaped quotes, so double quotes make conjunctions like "don't" easier to type.

    Regular HTML attributes also typically use double quotes instead of single, so JSX attributes mirror this convention.

1
2
3
4
5
6
7
8
9
10
11
// bad
<Foo bar='bar' />

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

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

// good
<Foo style={{ left: '20px' }} />
  • 必须在自关闭标签前加一个空格。
1
2
3
4
5
6
7
8
9
10
11
12
// bad
<Foo/>

// very bad
<Foo />

// bad
<Foo
/>

// good
<Foo />
  • 必须书写propTypes,规定每个可接受属性的类型,并对propTypes加以jsdoc说明。

  • 必须使用camalCase来命名props。

1
2
3
4
5
6
7
8
9
10
11
// bad
<Foo
UserName="hello"
phone_number={12345678}
/>

// good
<Foo
userName="hello"
phoneNumber={12345678}
/>
  • 必须当props的值为字面值true时,省略={true}
1
2
3
4
5
6
7
8
9
// bad
<Foo
hidden={true}
/>

// good
<Foo
hidden
/>
  • 必须在DOM片段前后加一对括号(),当DOM片段在一行以上时。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// bad
render() {
return <MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>;

}

// good
render() {
return (
<MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>
);

}

// good, when single line
render() {
const body = <div>hello</div>;
return <MyComponent>{body}</MyComponent>;
}
  • 必须将组件写成自关闭标签,当组件没有children时。
1
2
3
4
5
// bad
<Foo className="stuff"></Foo>

// good
<Foo className="stuff" />

  • 必须将关闭标签另起一行,当组件有多个props时。
1
2
3
4
5
6
7
8
9
10
// bad
<Foo
bar="bar"
baz="baz" />

// good
<Foo
bar="bar"
baz="baz"
/>
  • 必须将bind handler到this的动作放到构造函数中。

    Why? A bind call in the render path creates a brand new function on every single render.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// bad
class extends React.Component {
onClickDiv() {
// do stuff
}

render() {
return <div onClick={this.onClickDiv.bind(this)} />
}
}

// good
class extends React.Component {
constructor(props) {
super(props);

this.onClickDiv = this.onClickDiv.bind(this);
}

onClickDiv() {
// do stuff
}

render() {
return <div onClick={this.onClickDiv} />
}
}

  • 必须以如下的顺序排列JSX文件中的方法。

    1. displayName
    2. propTypes
    3. contextTypes
    4. childContextTypes
    5. mixins
    6. statics
    7. defaultProps
    8. getDefaultProps
    9. getInitialState
    10. getChildContext
    11. componentWillMount
    12. componentDidMount
    13. componentWillReceiveProps
    14. shouldComponentUpdate
    15. componentWillUpdate
    16. componentDidUpdate
    17. componentWillUnmount
    18. clickHandlers or eventHandlers like onClickSubmit() or onChangeDescription()
    19. getter methods for render like getSelectReason() or getFooterContent()
    20. Optional render methods like renderNavigation() or renderProfilePicture()
    21. render

更多的通用组件规范 [general-guide]

[基本的JSX书写规范] (#jsx-jsx)基础上,更多的通用的React组件开发规范。

1
2
3
4
5
6
7
8
9
10
11
12
13
// bad
render() {
var cleverFunction = function () {};
// ...
}

// good
{
cleverFunction() {},
render() {
// just use this.cleverFunction
}
}
  • 不建议在运行期生命周期中使用时间复杂度O(n2)及以上阶的算法。
  • 必须不允许出现观察者模式,如自定义addEventListener方法,或on, fire等。
  • 必须只能通过以下2种方法设置组件内部状态:
    • 通过父组件的render方法,改变子组件的props。
    • 通过子组件的setState方法。
  • 必须不允许为组件提供setXXX方法来改变其内部状态,除非该setXXX方法中仅包含一个setState调用,且完成了一个充分复杂的state转换。
  • 必须为所有回调在getDefaultProps给出空函数默认值_.noop
  • 可以提供与组件内部数据结构紧密相关的操作方法。这些方法可以实现为一个纯函数,即只依赖其所有的参数来得到其结果。这些方法可以放在组件的static域中。

微信公众号

前端修炼