React代码规范
-
components 展示性组件
里面一般存放ui组件,负责组件的外表,也就是组件如何渲染,具有很强的内聚性。展示性组件不关心渲染时使用的组件属性(Props)是如何获取到的,它只要知道有了这些Props后,组件应该如何渲染就足够了。属性如何获取,是容器性组件负责的事情。当展示性组件状态的变化需要同步到源数据时,需要调用容器性组件中的方法,这个方法一般也是通过Props传递给展示性组件。 -
containers 容器组件
负责业务流程逻辑的处理,如发送网络请求,处理请求数据,将处理过的数据传递给子组件的Props使用。同时,容器性组件提供源数据的方法,以Props方式传递给子组件,当子组件的状态变更引起源数据的变化时,子组件通过调用容器性组件提供的方法同步这些变化。 -
容器性组件和展示性组件可以相互嵌套,一个容器性组件可以包含多个展示性组件和其他的容器性组件;一个展示性组将也可以包含容器性组件和其他的展示性组件。这样的分工,可以使与组件渲染无直接关系的逻辑由容器性组件集中负责,展示性组件只关注组件的渲染逻辑,从而使展示性组件更容易被复用。对于非常简单的页面,一般只要一个容器性组件就足够了;但对于负责页面,则需要多个容器性组件,否则所有的业务逻辑都在一个容器性组件中处理的话,会导致这个组件非常复杂,同时这个组件获取到的源数据,可能需要经过很多层的组件Props的传递,才能到达最终使用的展示性组件。
基本规则
- 1.每个文件只包含一个 React 组件
- 2.使用 JSX 语法
- 3.使用class基础写组件,少用React.createClass
命名
- 扩展名: 使用 jsx 作为 React 组件的扩展名
- 文件名: 文件命名采用帕斯卡命名法,如:ReservationCard.jsx,以大写开头,index.js除外
- 页面目录统一以小写字母开头,遵循驼峰规则,
- 引用名: 组件引用采用帕斯卡命名法,其 实例采用驼峰式命名法。
// 反例
const reservationCard = require('./ReservationCard');
// 正例
const ReservationCard = require('./ReservationCard');
// 反例
const ReservationItem = <ReservationCard />;
// 正例
const reservationItem = <ReservationCard />;
组件命名: 使用文件名作为组件名。
- 例如:ReservationCard.jsx 组件的引用名应该是 ReservationCard。
然而,对于一个目录的根组件,应该使用 index.jsx 作为文件名,使用目录名作为组件名。
// 反例
const Footer = require('./Footer/Footer.jsx')
// 反例
const Footer = require('./Footer/index.jsx')
// 正例
const Footer = require('./Footer')
对齐
- 对于 JSX 语法,遵循下面的对齐风格
// 反例
<Foo superLongParam="bar"
anotherSuperLongParam="baz" />
// 正例
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
/>
// if props fit in one line then keep it on the same line
<Foo bar="bar" />
// children get indented normally
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
>
<Spazz />
</Foo>
引号
- 对于 JSX 使用双引号,对其它所有 JS 属性使用单引号
为什么?因为 JSX 属性不能包含被转移的引号,并且双引号使得如 "don't" 一样的连接词很容易被输入。
常规的 HTML 属性也应该使用双引号而不是单引号,JSX 属性反映了这个约定。
// 反例
<Foo bar='bar' />
// 正例
<Foo bar="bar" />
// 反例
<Foo style={{ left: "20px" }} />
// 正例
<Foo style={{ left: '20px' }} />
空格
- 在自闭和标签之前留一个空格
// 反例
<Foo/>
// 反例
<Foo />
// 反例
<Foo
/>
// 正例
<Foo />
属性
- 属性名采用驼峰式命名法
// 反例
<Foo
UserName="hello"
phone_number={12345678}
/>
// 正例
<Foo
userName="hello"
phoneNumber={12345678}
/>
括号
- 当组件跨行时,要用括号包裹 JSX 标签。eslint rules: react/wrap-multilines
// 反例
render() {
return <MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>;
}
// 正例
render() {
return (
<MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>
);
}
// 正例, when single line
render() {
const body = <div>hello</div>;
return <MyComponent>{body}</MyComponent>;
}
标签
- 没有子组件的父组件使用自闭和标签。eslint rules: react/self-closing-comp
// 反例
<Foo className="stuff"></Foo>
// 正例
<Foo className="stuff" />
- 如果组件有多行属性,闭合标签应写在新的一行上。
- eslint rules: react/jsx-closing-bracket-location
// 反例
<Foo
bar="bar"
baz="baz" />
// 正例
<Foo
bar="bar"
baz="baz"
/>
方法
- 不要对 React 组件的内置方法使用 underscore (下划线)前缀
// 反例
React.createClass({
_onClickSubmit() {
// do stuff
}
// other stuff
});
// 正例
class extends React.Component {
onClickSubmit() {
// do stuff
}
// other stuff
});
顺序
- 继承 React.Component 的类的方法遵循下面的顺序
constructor(){
super(props);
this.state = {
}
}
// optional static methods
getChildContext(){}
componentWillMount(){}
componentDidMount(){}
componentWillReceiveProps(){}
shouldComponentUpdate(){}
componentWillUpdate(){}
componentDidUpdate(){}
componentWillUnmount(){}
// clickHandlers or eventHandlers like
onClickSubmit() {}
onChangeDescription(){}
// getter methods for render like
getSelectReason() {}
// Optional render methods like
renderNavigation(){}
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;
网友评论