秦小

React.js 最佳实践的非官方指南

直到现在,我已经使用 React.js 一段时间了。在这个过程中,我开始形成了自己的一套 React.js 最佳实践。

下面的最佳实践主要关注组件(component)结构和JSX。尽管这写不是硬性的规则,这些我一直坚持使用的规则更多的是能帮助我写出更可读更加健壮和可维护的代码。

注意: 这篇文章不会解释例子中用到的 React 范式和惯用法。这最好还是由 React 小组的超棒的文档来解释吧。

组件组成(Component organisation)

对任何代码来说,保持一致性是很重要的。当然,这也包括构建你的 React 组件的代码了。我使用如下的模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
React.createClass({
propTypes: {},
mixins : [],
getInitialState: function() {},
getDefaultProps: function() {},
componentWillMount : function() {},
componentWillReceiveProps: function() {},
componentWillUnmount : function() {},
_parseData : function() {},
_onSelect : function() {},
render : function() {}
})

我喜欢在组件的顶部声明propTypes, 因为它们是一个组件很有用的向导, 告诉我们这个组件以怎样的方式被使用(关于这点参考下面的章节)。接下来是mixins, 因为它能让你一开始就了解这个组件对外部行为的使用和依赖。

我选择把left-cycle方法分成两组,组件实例生成之前的(比如: getInitialState, getDefaultProps)和 挂载(mounting)、更新(updating)、已挂载(mounted)循环(比如: componentWillMount, shouldComponentUpdate)。而且,我发现按照执行顺序排列生命周期方法使得推测逻辑变得更容易。

我总是把自定义的方法放在生命周期方法的后面,并且为这些方法加一个下划线前缀,让它们更好识别。我通常会根据它们的用途进行分组(如: 解析,事件处理 等等)。

render方法总是放在最后。render 方法是必须的生命周期方法,当我打开一个文件时几乎总是第一个先去找到它。所以呢,在所有的组件中让他处于一致的位置是实用的吧。

通常,混合器(mixins)同组件遵循相同的约定。

总是设置propTypes验证以求自文档化

我总会使用 propTypes 为最近接收的prop 设置验证。这提供了组件使用的自文档,告诉我们组件如何使用,需要传入哪些prop.

1
2
3
4
5
6
7
8
propTypes: {
arrayProp: React.PropTypes.array,
boolProp: React.PropTypes.bool,
funcProp: React.PropTypes.func,
numProp: React.PropTypes.number,
objProp: React.PropTypes.object,
stringProp: React.PropTypes.string,
}

JSX

不得不说,JSX 有时看起来很丑,这也通常是一些开发者对 React 丑拒的原因。但是,下面一些通用指导可以帮你搞定组件,让它们可读很多,让它们不再辣眼睛。

多行 JSX

不管返回的元素多么的少,我都会把嵌套的 JSX 写成多行的形式,并且添加缩进来增强可读性。例如:

1
2
3
4
5
6
return (
<div>
<ComponentOne />
<ComponentTwo />
</div>
);

而不是。。。

1
return (<div><ComponentOne /><ComponentTwo /></div>);

而且,就算单行的 JSX 语句技术上不需要括号,我还是会添上括号,只为了代码的一致性。(还因为没有约束的在我的JS代码里飘来飘去的东东会让我的左眼不受控制的抽搐。。。)

条件 JSX

当我有一些这样条件元素(依据state, prop, 或其他的条件返回的元素)时,我会在 render 方法顶部声明一个空的变量,只在条件成立时才把 JSX 传给这个变量 。 当这个变量在 render 方法的返回语句中返回值时,条件元素同时也会被渲染,空值是则不渲染条件元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
var optionalElement;
if (this.props.condition) {
optionalElement = (<div> … </div>);
}
return (
<div>
{optionalElement}
</div>
);

内联列表迭代

在可能的情况下,我喜欢在返回的 JSX 中对数据列表进行内联迭代。除非迭代的内部逻辑太过复杂,需要移到返回语句之外生成一个可供渲染数组。

1
2
3
4
5
6
7
return (
<div>
{this.props.list.map(function(data, i) {
return (<Component data={data} key={i} />)
})}
</div>
);

缩进、组件属性独占一行

当组件的属性多到(通常3个或以上)在单行中显示不整洁时,我都会写成多行的形式,并添加缩进。是这样:

1
2
3
4
5
6
<Component
attribute={...}
anotherAttribute={...}
attributeThree={...}
/>

而不是。。。

1
<Component attribute={...} anotherAttribute={...} attributeThree={...} />

总结

这些规则并非权威的详尽的指南,但我觉得算是一个好的组织和标准化 React 组件的起点吧。另外我还遇到这些约定的一些其他通用使用场景。

希望这些规则能为你提供一个组织 React 组件的有用的起点。