搜集并总结的一些React书写规范,帮助使用React开发者更好的构建项目中的代码。
基本规范
- 每个文件只写一个模块, 但如果有多个无状态的可以写在一个文件里。
- 推荐使用JSX语法。
- 不要使用
React.createElement
,除非从一个非JSX的文件中初始化你的app。
创建模块
- 如果你的模块有内部状态或者是
refs
, 推荐使用class extends React.Component
。
// bad
const Going = React.createClass({
// ...
render() {
return <div>{this.state.happy}</div>;
}
});
// good
class Going extends React.Component {
// ...
render() {
return <div>{this.state.happy}</div>;
}
}
- 如果你的模块没有状态或是没有引用
refs
, 推荐使用普通函数(非箭头函数)而不是类。
// bad
class Going extends React.Component {
render() {
return <div>{this.props.happy}</div>;
}
}
// bad
const Going = ({ happy }) => (
<div>{happy}</div>
);
// good
function Going({ happy }) {
return <div>{happy}</div>;
}
命名
- 文件名: 文件名使用帕斯卡命名. 如,
GoOn.jsx
。 - 引用命名: React模块名使用帕斯卡命名。
- 实例使用骆驼式命名。
// bad
import goOn from './GoOn';
// good
import GoOn from './GoOn';
// bad
const GoOn = <GoOn />;
// good
const goOn = <GoOn />;
- 属性命名。
// bad
<MyComponent className="some" />
// good
<MyComponent name="some" />
声明模块
// bad
export default React.createClass({
//.......
});
// good
export default class GoOn extends React.Component {
//.......
}
代码对齐
// bad
<GoOn aParam="bar"
bParam="baz" />
// good, 有多行属性的话, 新建一行关闭标签
<GoOn
aParam="bar"
bParam="baz"
/>
// 若能在一行中显示, 直接写成一行(注意闭标签与属性之间的空格)
<GoOn aParam ="bar" />
// 子元素按照常规方式缩进
<GoOn
aParam="bar"
bParam="baz"
>
<Something />
</GoOn>
单引号还是双引号
- 对于JSX属性值总是使用双引号
(")
, 其他均使用单引号(')
。
为什么? HTML属性也是用双引号, 因此JSX的属性也遵循此约定。
// bad
<GoOn happy='happy' />
// good
<GoOn happy="happy" />
// bad
<GoOn style={{ left: "20px" }} />
// good
<GoOn style={{ left: '20px' }} />
属性
- JSX属性名使用骆驼式风格。
// bad
<Person
UserName="hello"
phone_number={ 12345678 }
/>
// good
<Person
userName="hello"
phoneNumber={ 12345678 }
/>
- 如果属性值为
true
, 可以直接省略。
// bad
<GoOn happy={ true } />
// good
<GoOn happy />
Refs
- 总是在
Refs
里使用回调函数(详见)。
// bad
<GoOn
ref="myRef"
/>
// good
<GoOn
ref={(ref) => { this.myRef = ref; }}
/>
标签
- 对于没有子元素的标签来说总是自己关闭标签。
// bad
<GoOn className="something"></Foo>
// good
<GoOn className="something" />
函数
- 使用箭头函数来获取本地变量。
function ItemList(props) {
return (
<ul>
{props.items.map((item, index) => (
<Item
key={item.key}
onClick={() => doSomethingWith(item.name, index)}
/>
))}
</ul>
);
}
- 当在
render()
里使用事件处理方法时,提前在构造函数里把this
绑定上去。(详见)。
为什么? 在每次
render
过程中, 再调用bind
都会新建一个新的函数,浪费资源。
// 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} />
}
}
模块生命周期
-
class extends React.Component
的生命周期函数:(详见)
- 可选的
static
方法 -
constructor
构造函数 -
componentWillMount
模块渲染前 -
componentDidMount
模块渲染后 -
componentWillReceiveProps
模块将接受新的数据 -
shouldComponentUpdate
判断模块需不需要重新渲染 -
componentWillUpdate
上面的方法返回true
, 模块将重新渲染 -
componentDidUpdate
模块渲染结束 -
componentWillUnmount
模块将从DOM
中清除, 做一些清理任务 -
render render()
方法
- 如何定义 propTypes, defaultProps, contextTypes, 等等其他属性。
import React, { PropTypes } from 'react';
const propTypes = {
id: PropTypes.number.isRequired,
url: PropTypes.string.isRequired,
text: PropTypes.string,
};
const defaultProps = {
text: 'Hello World',
};
class Link extends React.Component {
static methodsAreOk() {
return true;
}
render() {
return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a>
}
}
Link.propTypes = propTypes;
Link.defaultProps = defaultProps;
export default Link;
- 对于所有非必须的属性,总是手动去定义defaultProps属性。
为什么? propTypes 可以作为模块的文档说明, 并且声明 defaultProps 的话意味着阅读代码的人不需要去假设一些默认值。更重要的是, 显示的声明默认属性可以让你的模块跳过属性类型的检查。