Update react编码规范.md

This commit is contained in:
ZhouBoyu 2017-10-17 09:50:53 +08:00 committed by GitHub
parent 6442be2e6f
commit 429bee54bb
1 changed files with 441 additions and 15 deletions

View File

@ -6,31 +6,457 @@
- 每一个文件只包含一个组件,每一个基本组件只包含单一功能
- src目录下如果文件返回是一个类文件名首字母大写
- 文件js模块统一使用js后缀名
- 测试用例文件名使用.spec.js后缀
- 每一个组件使用一个单独的测试用例文件
## js规范
- 使用es6开发尽量使用常用的ES6语法(ES6语法参考)[http://es6.ruanyifeng.com/]
- 使用jsx语法
- 组件仓库命名为小写和“-”连接如button、button-group
### 格式
- 标签自闭合
```
//bad
<Button></Button>
//good
<Button />
```
- 自闭合换行
```
//bad
<Button color="primary" />
//good
<Button
color="primary"
/>
```
-
### 组件命名
- 组件文件命名使用大驼峰, ComponentDemo
- 带命名空间的组件如果一个组件包含只有自身使用的子组件以该组件为命名空间编写组件例如TableTable.Head
- 不使用displayName命名
- 自定义属性使用data-
### 组件声明
- 使用es6的class来声明组件而不是使用`createClass`,在React V16版本`createClass`已经废弃
```
// bad
const Button = React.createClass({
// ...
render() {
return <button>{this.state.hello}</button>;
}
});
// good
class Button extends React.Component {
// ...
render() {
return <button>{this.state.hello}</button>;
}
```
- 对于不包含`state`和`refs`的组件建议写成纯函数组件而且建议使用function关键字声明
```
//bad
class Button extends React.Component{
render() {
return (
<Button>{ this.props.text }</Button>
)
}
}
//bad
const Button = ({ text }) => (
<button>{ text }</button>
)
//good
function Button ({ text }) {
return (
<button>{ text }</button>
)
}
```
- 对于只有简单数据类型的`props`和`state`的组件,建议使用`PureComponent`来声明组件
```
//bad
class Button extends React.Component{
constructor(props){
super(props);
this.state = {
disabled: false
}
}
render() {
return (
<Button
disabled={this.state.disabled}>
{ this.props.text }
</Button>
)
}
}
//good
class Button extends React.PureComponent{
constructor(props){
super(props);
this.state = {
disabled: false
}
}
render() {
return (
<Button
disabled={this.state.disabled}>
{ this.props.text }
</Button>
)
}
}
```
### 组件内部声明
- 使用propTypes进行props类型校验
```
import PropTypes from 'prop-types';
const propTypes = {
disabled: PropTypes.bool
}
class Button extends React.Component{}
Button.propTypes = propTypes;
```
- 使用defaultProps定义默认参数
```
import PropTypes from 'prop-types';
const defaultProps = {
disabled: false
}
class Button extends React.Component{}
Button.defaultProps = defaultProps;
```
- 不使用displayName命名
displayName属性用于组件调试时输出显示JSX自动设置该值可以理解为调试时显示的组件名。
```
// bad
export default React.createClass({
displayName: 'Button',
// stuff goes here
});
// good
export default class Button extends React.Component {
}
```
### 属性定义
- 定义props避开react关键字及保留字常用的props及state定义可参考下表
- `props`和`state`使用驼峰命名。
- 不直接修改`state`
```
//bad
class Button extends React.Component{
constructor(props){
super(props);
this.state = {
disabled: false
}
}
handleClick = () => {
this.state.disabled = true;
this.setState({
disabled: this.state.disabled
})
}
render() {
return (
<Button
disabled={this.state.disabled}>
{ this.props.text }
</Button>
)
}
}
//good
class Button extends React.Component{
constructor(props){
super(props);
this.state = {
disabled: false
}
}
handleClick = () => {
let disabled = ture;
this.setState({
disabled
})
}
render() {
return (
<Button
disabled={this.state.disabled}>
{ this.props.text }
</Button>
)
}
}
```
- 自定义HTML属性使用data-
```
class Button extends React.Component{
render() {
return (
<Button
data-name="submit-button">
{ this.props.text }
</Button>
)
}
}
```
- 可以使用es6的这种`...props`语法获取剩下所有属性,但是如果没有必要,尽量不要使用
```
class Button extends React.Component{
render() {
let {onClick, disabled, ...props} = this.props;
return (
<Button
{ ...props }>
{ this.props.text }
</Button>
)
}
}
```
### ref
- 通过`ref`可以取到组件原生dom对象。使用传入函数function方式来定义`ref`,不使用字符串定义`ref`
```
//bad
class Button extends React.Component{
constructor(props){
super(props);
}
componentDidMount() {
this.refs.buttonRef.focus();
}
render() {
return (
<Button
ref="buttonRef">
{ this.props.text }
</Button>
)
}
}
//good
class Button extends React.Component{
constructor(props){
super(props);
this.buttonRef = {};
}
componentDidMount() {
this.buttonRef.focus();
}
render() {
return (
<Button
ref={(el) => this.buttonRef = el;}>
{ this.props.text }
</Button>
)
}
}
```
- 尽量少或者不使用ref获取和操作dom节点使用state和prop进行控制dom
- 事件调用使用在元素上onClick调用
- 注意react和html的表单元素的差异
- 使用es6后不支持mixin使用decorator进行扩展babel需要增加解析器和高阶组件方式扩展。
- 尽量不使用比较大的第三方js库
- 组件方法定义顺序 constructor --> 声明周期方法(componentWillMount,componentDidMount,
componentWillUpdate,componentDidUpdate,componentWillUnmount)
- 尽量多而有用的代码注释,方法用块级注释,结构如下例。
- 有必要需要些组件的销毁方法,比如 定时器,需要用销毁方法销毁定时器
- ...others 没有必要 勿用
- 自身定义的props属性应避免与react的关键字相同
### 组件声明周期函数
- 组件方法定义顺序
- constructor
- getChildContext
- componentWillMount
- componentDidMount
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- componentDidUpdate
- componentWillUnmount
- 在`componentDidMount`生命周期内获取初始数据
```
class Button extends React.Component{
constructor(props){
super(props);
this.state = {
data: ''
}
}
componentDidMount() {
axios.get('http://baidu.com/button-name')
.then((res) => {
this.setState({
datares.data
})
})
}
render() {
return (
<Button>
{ this.state.data }
</Button>
)
}
}
```
- 在组件`componentWillUnmount`卸载生命周期中,进行清除定时器、卸载组件绑定的自定义事件等。
```
class Button extends React.Component{
constructor(props){
super(props);
this.state = {
data: ''
}
this.timer = null;
}
componentDidMount() {
this.timer = setInterval(this.getData, 1000);
}
getData = () => {
axios.get('http://baidu.com/button-name')
.then((res) => {
this.setState({
datares.data
})
})
}
componentWillUnmount() {
window.clearInterval(this.timer);
}
render() {
return (
<Button>
{ this.state.data }
</Button>
)
}
}
```
- 使用箭头函数定义自定义的组件内方法
```
//bad
class Button extends React.Component{
handleClick(e) {
}
render() {
return (
<Button onClick={this.handleClick.bind(this)}>
{ this.state.data }
</Button>
)
}
}
//good
class Button extends React.Component{
handleClick = (e) => {
}
render() {
return (
<Button onClick={this.handleClick}>
{ this.state.data }
</Button>
)
}
}
```
### Mixin
- 使用es6后不支持mixin使用decorator进行扩展和高阶组件方式扩展。