Airbnb React/JSX 编码规范

简介

参考

算是最合理的React/JSX编码规范之一了。

Create创建模块

如果你的模块有内部状态或者是refs, 推荐使用 class extends React.Component 而不是 React.createClass。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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>;
}
}

如果你的模块没有状态或是没有引用refs, 推荐使用普通函数(非箭头函数)而不是类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 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>;
}

Naming 命名

  • 文件名: 文件名使用帕斯卡命名. 如, ReservationCard.jsx.
  • 引用命名: React模块名使用帕斯卡命名,实例使用骆驼式命名.
1
2
3
4
5
6
7
8
9
10
11
// 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 或者文件夹名作为模块的名称:
1
2
3
4
5
6
7
8
// bad
import Footer from './Footer/Footer';

// bad
import Footer from './Footer/index';

// good
import Footer from './Footer';
  • 属性命名: 避免使用DOM相关的属性来用作其他的用途。
1
2
3
4
5
// bad
<MyComponent style="fancy" />

// good
<MyComponent variant="fancy" />

Alignment 代码对齐

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"
/>

// 若能在一行中显示, 直接写成一行
<Foo bar="bar" />

// 子元素按照常规方式缩进
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
>
<Quux />
</Foo>

Quotes 单引号还是双引号

  • 对于JSX属性值总是使用双引号(“), 其他均使用单引号(‘).

为什么? HTML属性也是用双引号, 因此JSX的属性也遵循此约定.

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' }} />

Props 属性

  • JSX属性名使用骆驼式风格camelCase.
1
2
3
4
5
6
7
8
9
// bad

<foo username="hello" phone_number="{12345678}">
</foo>

// good

<foo username="hello" phonenumber="{12345678}">
</foo>
  • 如果属性值为 true, 可以直接省略.
1
2
3
4
5
6
7
8
9
10
11
12
13

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

// good
<Foo
hidden
/>

// good
<Foo hidden />
  • 避免使用数组的index来作为属性key的值,推荐使用唯一ID.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

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

// good
{todos.map(todo => (
<Todo
{...todo}
key={todo.id}
/>
))}
  • 对于所有非必须的属性,总是手动去定义defaultProps属性.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// bad
function SFC({ foo, bar, children }) {
return <div>{foo}{bar}{children}</div>;
}
SFC.propTypes = {
foo: PropTypes.number.isRequired,
bar: PropTypes.string,
children: PropTypes.node,
};

// good
function SFC({ foo, bar, children }) {
return <div>{foo}{bar}{children}</div>;
}
SFC.propTypes = {
foo: PropTypes.number.isRequired,
bar: PropTypes.string,
children: PropTypes.node,
};
SFC.defaultProps = {
bar: '',
children: null,
};
  • 特别提醒:尽可能地筛选出不必要的属性。
1
2
3
4
5
6
7
8
9
10
11
//good
render() {
const { irrelevantProp, ...relevantProps } = this.props;
return <WrappedComponent {...relevantProps} />
}

//bad
render() {
const { irrelevantProp, ...relevantProps } = this.props;
return <WrappedComponent {...this.props} />
}

Refs

  • 总是在Refs里使用回调函数
1
2
3
4
5
6
7
8
9
// bad
<Foo
ref="myRef"
/>

// good ???
<Foo
ref={(ref) => { this.myRef = ref; }}
/>

Parentheses 括号

  • 将多行的JSX标签写在 ()里
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, 单行可以不需要
render() {
const body = <div>hello</div>;
return <MyComponent>{body}</MyComponent>;
}

Methods 函数

  • 当在 render() 里使用事件处理方法时,提前在构造函数里把 this 绑定上去

为什么? 在每次 render 过程中, 再调用 bind 都会新建一个新的函数,浪费资源.

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} />;
}
}
  • 在 render 方法中总是确保 return 返回值
1
2
3
4
5
6
7
8
9
// bad
render() {
(<div />);
}

// good
render() {
return (<div />);
}

Object 定义对象的细节

逗号问题

  • 单行定义的对象结尾不要逗号:
1
2
3
4
5
// bad
const a = { k1: v1, k2: v2, };

// good
const a = { k1: v1, k2: v2 };
  • 多行定义的对象要保留逗号:
1
2
3
4
5
6
7
8
9
10
11
// bad
const b = {
k1: v1,
k2: v2
};

// good
const b = {
k1: v1,
k2: v2,
};

一次性初始化完全

  • 不要声明之后又给对象添加新属性:
1
2
3
4
5
6
7
// bad
const a = {};
a.x = 3;

// good
const a = { x: null };
a.x = 3;
  • 如果一定非要加请使用Object.assign:
1
2
const a = {};
Object.assign(a, { x: 3 });
0%