- 基本规范
- ES6写法React class
- Do Not Use mixins
- 命名
- 声明模块
- 代码对齐
- 单引号还是双引号
- 空格
- 属性
- Refs引用
- 括号
- 标签
- 函数/方法
- 模块生命周期
- 语法规范及原则
- 组件设计原则
- 每个文件只写一个组件.
- 推荐使用JSX语法.
- 不要使用
React.createElement
.
// bad
const Listing = React.createClass({
// ...
render() {
return <div>{this.state.hello}</div>;
}
});
// good
class Listing extends React.Component {
// ...
render() {
return <div>{this.state.hello}</div>;
}
}
// bad
class Listing extends React.Component {
render() {
return <div>{this.props.hello}</div>;
}
}
// bad (relying on function name inference is discouraged)
const Listing = ({ hello }) => (
<div>{hello}</div>
);
// good
function Listing({ hello }) {
return <div>{hello}</div>;
}
- 不要使用 mixins
- 不要使用 contextTypes
-
扩展名: React模块使用
.jsx
扩展名. - 文件名: 文件名使用帕斯卡命名. 如,ReservationCard.jsx
.// bad import reservationCard from './ReservationCard'; // good import ReservationCard from './ReservationCard'; // bad const ReservationItem = <ReservationCard />; // good const reservationItem = <ReservationCard />;
-
模块命名: 模块使用当前文件名一样的名称. 比如
ReservationCard.jsx
应该包含名为ReservationCard
的模块. 但是,如果整个文件夹是一个模块,使用index.js
作为入口文件,然后直接使用index.js
或者文件夹名作为模块的名称:// bad import Footer from './Footer/Footer'; // bad import Footer from './Footer/index'; // good import Footer from './Footer/';
-
高阶模块命名: 对于生成一个新的模块,其中的模块名
displayName
应该为高阶模块名和传入模块名的组合. 例如, 高阶模块withFoo()
, 当传入一个Bar
模块的时候, 生成的模块名displayName
应该为withFoo(Bar)
.// bad export default function withFoo(WrappedComponent) { return function WithFoo(props) { return <WrappedComponent {...props} foo />; } } // good export default function withFoo(WrappedComponent) { function WithFoo(props) { return <WrappedComponent {...props} foo />; } const wrappedComponentName = WrappedComponent.displayName || WrappedComponent.name || 'Component'; WithFoo.displayName = `withFoo(${wrappedComponentName})`; return WithFoo; }
-
属性命名: 避免使用DOM相关的属性来用作其他的用途。
// bad <MyComponent style="fancy" /> // good <MyComponent variant="fancy" />
-
不要使用
displayName
来命名React模块,而是使用引用来命名模块, 如 class 名称.// bad export default React.createClass({ displayName: 'ReservationCard', // stuff goes here }); // good export default class ReservationCard extends React.Component { }
-
遵循以下的JSX语法缩进/格式.
// good, 有多行属性的话 <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // bad <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // 若能在一行中显示, 直接写成一行 <Foo bar="bar" />
- 对于JSX属性值总是使用双引号(
"
), 其他均使用单引号('
).
为什么? HTML属性也是用双引号, 因此JSX的属性也遵循此约定.
```jsx
// bad
<Foo bar='bar' />
// good
<Foo bar="bar" />
// bad
<Foo style={{ left: "20px" }} />
// good
<Foo style={{ left: '20px' }} />
```
-
总是在自动关闭的标签前加一个空格,正常情况下也不需要换行.
// very bad <Foo /> // bad <Foo /> // good <Foo />
-
不要在JSX
{}
引用括号里两边加空格.// bad <Foo bar={ baz } /> // good <Foo bar={baz} />
-
JSX属性名使用骆驼式风格
camelCase
.// bad <Foo UserName="hello" phone_number={12345678} /> // good <Foo userName="hello" phoneNumber={12345678}/>
-
如果属性值为
true
, 可以直接省略.// bad <Foo hidden={true} /> // good <Foo hidden />
-
避免使用数组的index来作为属性
key
的值,推荐使用唯一ID.
// bad
{todos.map((todo, index) =>
<Todo {...todo}
key={index} />
)}
// good
{todos.map(todo => (
<Todo {...todo}
key={todo.id}/>
))}
- 对于所有非必须的属性,总是手动去定义
defaultProps
属性.
propTypes 可以作为模块的文档说明, 并且声明 defaultProps 的话意味着阅读代码的人不需要去假设一些默认值。更重要的是, 显示的声明默认属性可以让你的模块跳过属性类型的检查.
// good
import { Component,PropTypes },React from 'react';
import {render} from 'react-dom';
class BusinessLogic extends Component{
/*
* 对每个prop含义必须进行注释
* 说明每个prop的类型
*/
static propTypes={
velocity:PropTypes.number,//滚动速度
imageArray: PropTypes.array// 图片源
}
/*
* props默认参数
*/
static defaultProps={
velocity:500,//滚动速度
imageArray:[],//图片源
}
//不要使用context
constructor(props,context){
super();
this.state = {}
}
render(){
return <你的逻辑>
}
}
-
总是在Refs里使用回调函数.
// bad <Foo ref="myRef"/> // good <Foo ref={(ref) => { this.myRef = ref; }}/>
-
将多行的JSX标签写在
()
里.// bad render() { return <MyComponent className="long body" foo="bar"> <MyChild /> </MyComponent>; } // good render() { return ( <MyComponent className="long body" foo="bar"> <MyChild /> </MyComponent> ); } // good, 单行可以不需要 render() { const body = <div>hello</div>; return <MyComponent>{body}</MyComponent>; }
-
对于没有子元素的标签来说总是自己关闭标签.
// bad <Foo className="stuff"></Foo> // good <Foo className="stuff" />
- 使用箭头函数来获取本地变量.
function ItemList(props) {
return (
<ul>
{props.items.map((item, index) => (
<Item
key={item.key}
onClick={() => doSomethingWith(item.name, index)}
/>
))}
</ul>
);
}
- 在React模块中不要给私有函数添加
_
前缀
// bad
React.createClass({
_onClickSubmit() {
// do stuff
},
// other stuff
});
// good
class extends React.Component {
onClickSubmit() {
// do stuff
}
// other stuff
}
class extends React.Component
的生命周期函数:
- 可选的
static
方法 constructor
构造函数componentWillMount
模块渲染前componentDidMount
模块渲染后componentWillReceiveProps
模块将接受新的数据shouldComponentUpdate
判断模块需不需要重新渲染componentWillUpdate
上面的方法返回true
, 模块将重新渲染componentDidUpdate
模块渲染结束componentWillUnmount
模块将从DOM中清除, 做一些清理任务- 点击回调或者事件处理器 如
onClickSubmit()
或onChangeDescription()
render
里的 getter 方法 如getSelectReason()
或getFooterContent()
- 可选的 render 方法 如
renderNavigation()
或renderProfilePicture()
render
render() 方法
- @,decorator语法来组装高阶组件
@connect()
class Test extends Component{
}
- do expression来处理简单的条件分支逻辑
do{
if(condition1){
<Component1 />
}else if(condition2){
<Component2 />
}else{
<Component3 />
}
}
- state和props数据信息保持最小的重复性
- state和props不要有信息重复。
- 功能单一及DRY原则
- 代码编写不要出现重复代码