Airbnb的编码规范是在业界非常流行的一套规范,而且它一直都在进化,推出最新技术的规范,例如第一时间推出了ES6的规范,让人读了感觉受益匪浅,突然发现最近更新了React的编码规范,所以第一时间翻译了过来,而且现在React如日中天,采用这个库的作为解决方案的各位,不妨读一读这个规范,借鉴学习,写出漂亮的代码。原文在此:javascript/react at master · airbnb/javascript · GitHub 欢迎各位和原文对比,并提出意见。
用更合理的方式书写React和JSX
基本规则
Class vs React.createClass vs stateless
- 如果组件拥有内部的 state 或者 refs 的时,更推荐使用
class extends React.Component,除非你有一个非常好的理由要使用 mixin。 eslint:react/prefer-es6-class
// bad
const Listing = React.createClass({
// ...
render() {
return {this.state.hello};
}
});
// good
class Listing extends React.Component {
// ...
render() {
return {this.state.hello};
}
}
如果没有组件没有内部 state 或者 refs,那么普通函数 (不要使用箭头函数) 比类的写法更好:
// bad
class Listing extends React.Component {
render() {
return {this.props.hello};
}
}
// bad (因为箭头函数没有“name”属性)
const Listing = ({ hello }) => (
{hello}
);
// good
function Listing({ hello }) {
return {hello};
}
命名
- 扩展名:React 组件使用
.jsx扩展名; - 文件名:文件名使用帕斯卡命名。 例如:
ReservationCard.jsx。 - 引用命名:React 组件使用帕斯卡命名,引用实例采用骆驼命名。 eslint:
react/jsx-pascal-case
// bad
import reservationCard from './ReservationCard';
// good
import ReservationCard from './ReservationCard';
// bad
const ReservationItem = ;
// good
const reservationItem = ;
- 组件命名:组件名称应该和文件名一致, 例如:
ReservationCard.jsx应该有一个ReservationCard的引用名称。 但是, 如果是在目录中的组件, 应该使用index.jsx作为文件名 并且使用文件夹名称作为组件名:
// bad
import Footer from './Footer/Footer';
// bad
import Footer from './Footer/index';
// good
import Footer from './Footer';
声明
- 不要使用`displayName`属性来命名组件,应该使用类的引用名称。
// bad
export default React.createClass({
displayName: 'ReservationCard',
// stuff goes here
});
// good
export default class ReservationCard extends React.Component {
}
对齐
- 为 JSX 语法使用下列的对其方式。eslint:
react/jsx-closing-bracket-location
// bad
// good
// 如果组件的属性可以放在一行就保持在当前一行中
// 多行属性采用缩进
引号
- JSX 的属性都采用双引号,其他的 JS 都使用单引号。eslint:
jsx-quotes
为什么这样做?JSX 属性 不能包含转义的引号, 所以当输入
"don't"这类的缩写的时候用双引号会更方便。
标准的 HTML 属性通常也会使用双引号,所以 JSX 属性也会遵守这样的约定。
// bad
// good
// bad
// good
空格
// bad
// very bad
// bad
// good
属性
// bad
// good
- 当属性值等于
true的时候,省略该属性的赋值。 eslint:react/jsx-boolean-value
// bad
// good
大括号
- 用括号包裹多行 JSX 标签。 eslint:
react/wrap-multilines
// bad
render() {
return
;
}
// good
render() {
return (
);
}
// good, when single line
render() {
const body = hello;
return {body};
}
标签
- 当标签没有子元素时,始终时候自闭合标签。 eslint:
react/self-closing-comp
// bad
// good
- 如果控件有多行属性,关闭标签要另起一行。 eslint:
react/jsx-closing-bracket-location
// bad
// good
方法
- 在 render 方法中事件的回调函数,应该在构造函数中进行bind绑定。 eslint:
react/jsx-no-bind
为什么这样做? 在 render 方法中的 bind 调用每次调用 render 的时候都会创建一个全新的函数。
// bad class extends React.Component { onClickDiv() { // do stuff } render() { return} } // good class extends React.Component { constructor(props) { super(props); this.onClickDiv = this.onClickDiv.bind(this); } onClickDiv() { // do stuff } render() { return} }
- React 组件的内部方法命名不要使用下划线前缀。
// bad
React.createClass({
_onClickSubmit() {
// do stuff
},
// other stuff
});
// good
class extends React.Component {
onClickSubmit() {
// do stuff
}
// other stuff
}
排序
class extends React.Component的顺序:
static静态方法constructorgetChildContextcomponentWillMountcomponentDidMountcomponentWillReceivePropsshouldComponentUpdatecomponentWillUpdatecomponentDidUpdatecomponentWillUnmount- 点击回调或者事件回调 比如
onClickSubmit()或者onChangeDescription() render函数中的 getter 方法 比如getSelectReason()或者getFooterContent()- 可选的 render 方法 比如
renderNavigation()或者renderProfilePicture() 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 {this.props.text}
}
}
Link.propTypes = propTypes;
Link.defaultProps = defaultProps;
export default Link;
React.createClass的排序:eslint:react/sort-comp
displayNamepropTypescontextTypeschildContextTypesmixinsstaticsdefaultPropsgetDefaultPropsgetInitialStategetChildContextcomponentWillMountcomponentDidMountcomponentWillReceivePropsshouldComponentUpdatecomponentWillUpdatecomponentDidUpdatecomponentWillUnmount- clickHandlers or eventHandlers like
onClickSubmit()oronChangeDescription() - getter methods for
renderlikegetSelectReason()orgetFooterContent() - Optional render methods like
renderNavigation()orrenderProfilePicture() - 点击回调或者事件回调 比如
onClickSubmit()或者onChangeDescription() render函数中的 getter 方法 比如getSelectReason()或者getFooterContent()- 可选的 render 方法 比如
renderNavigation()或者renderProfilePicture() render
isMounted
- 不要使用
isMounted. eslint:react/no-is-mounted
为什么这样做?
isMounted是一种反模式,当使用 ES6 类风格声明 React 组件时该属性不可用,并且即将被官方弃用。