<React> 代码规范和风格指南

375 阅读4分钟

1、最重要的生命周期规范

class Example extends Component {
    // 静态属性
    static defaultProps = {}

    // 构造函数
    constructor(props) {
        super(props);
        this.state={}
    }

    // 声明周期钩子函数
    // 按照它们执行的顺序
    // 1. componentWillMount
    // 2. componentWillReceiveProps
    // 3. shouldComponentUpdate
    // 4. componentDidMount
    // 5. componentDidUpdate
    // 6. componentWillUnmount
    componentDidMount() { ... }

    // 事件函数/普通函数
    handleClick = (e) => { ... }

    // 最后,render 方法
    render() { ... }
}

2、无状态组件: 函数式组件

无交互逻辑和业务数据

没有使用构造函数、没有使用方法,没必要使用class继承

only Render函数

性能好

import React from "react";
import List from '../../pages/list/list';

const Index = () => {
    return(
        <div style={{paddingTop:'50px',width: '600px', margin: '0 auto'}}>
            <List/>
        </div>
    )
};
export default Index;

3、有状态组件: class

丰富的交互逻辑和业务数据

import React, { Component } from "react";
import ListInput from "./components/ListInput";
import ListLi from './components/ListLi'
import { Card, Button } from "antd";


class List extends Component{
    constructor(props) {
        super(props);
        this.state = {
            list: ['测试1', '测试2'],
            value: ''
        };
    };
    // 增加
    addItem = () => {
        let { list, value } = this.state;
        if(!value){
            return;
        }
        list.push(value);
        value = '';
        this.setState({
            list,
            value
        },() => {
            console.log(this.ul.querySelectorAll('li').length);
        });
    };
    // 改变
    onChange = (content) => {
        let { value } = this.state;
        value = content;
        this.setState({
            value
        })
    };
    // 删除
    deleteItem = (index) => {
        let { list } = this.state;
        list.splice(index, 1);
        this.setState({
            list
        })
    };
    render() {
        console.log('组件挂在中');
        let { list, value } = this.state;
        const listLi = list.map((item, index) => {
            return (
                <ListLi key={index} item={item} index={index} deleteItem={this.deleteItem.bind(this)} />
            )
        });
        const noLi = '暂无更多';
        return (
            <div style={{width: '100%'}}>
                <Card title='todo' style={{marginBottom: '30px'}}>
                    <ListInput value={value} onChange={this.onChange.bind(this)}  />
                    <Button style={{marginTop: '30px'}} type='primary' onClick={ this.addItem } >新增</Button>
                </Card>
                <Card title='列表' style={{marginBottom: '30px'}}>
                    <ul ref={(ul) => {this.ul = ul}}>
                        {
                            list.length > 0 ? listLi : noLi
                        }
                    </ul>
                </Card>

            </div>
        )
    }
}
export  default  List

4、redux的使用

一、使用actionTypes规范每个action的名字,避免写错不报错的发生

二、actionCreators统一创建action,避免往后逻辑混乱

5、组件声明

推荐

import Footer from './Footer';

不推荐

import Footer from './Footer/index';

6、组件声明

  • 组件名称: 推荐使用大驼峰命名;

  • 属性名称: React DOM 使用小驼峰命令来定义属性的名称,而不使用 HTML 属性名称的命名约定;

  • style 样式属性: 采用小驼峰命名属性的 JavaScript 对象

推荐

// 组件名称
MyComponent
// 属性名称
onClick
// 样式属性
backgroundColor

7、JSX 写法注意

1、标签

(1)当标签没有子元素的时候,始终使用自闭合的标签 。

// Good
<Component />

(2)如果标签有多行属性,关闭标签要另起一行

<Component
  bar="bar"
  baz="baz" 
/>

(3)在自闭标签之前留一个空格。

<Foo />

(4)当组件跨行时,要用括号包裹 JSX 标签。

 render() {
    return (
      <MyComponent className="long body" foo="bar">
        <MyChild />
      </MyComponent>
    );
  }

2、对齐

// 推荐
<Foo
  superLongParam="bar"
  anotherSuperLongParam="baz"
/>

// 如果组件的属性可以放在一行(一个属性时)就保持在当前一行中
<Foo bar="bar" />

// 多行属性采用缩进
<Foo
  superLongParam="bar"
  anotherSuperLongParam="baz"
>
  <Quux />
</Foo>

3、引号

JSX 的属性都采用双引号,其他的 JS 都使用单引号 ,因为 JSX 属性 不能包含转义的引号, 所以当输入 "don't" 这类的缩写的时候用双引号会更方便。

<Foo bar="bar" />
<Foo style={{ left: '20px' }} />

8、defaultProps 使用静态属性定义

defaultProps 推荐使用静态属性定义,不推荐在 class 外进行定义。

推荐:

class Example extends React.Component {
  static defaultProps = {
    name: 'stranger'
  }

  render() {
   // ...
  }
}

不推荐:

class Example extends React.Component {
  render() {
    // ...
  }
}

Example.propTypes = {
  name: PropTypes.string
};

9、key 属性设置

key的值等于id更好

万不得已可以使用元素索引 index 作为 key,但是要主要如果列表项目的顺序可能会变化,如果使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题。

10、State

1、不要直接修改 state

除了 state 初始化外,其它地方修改 state,需要使用 setState( ) 方法,否则如果直接赋值,则不会重新渲染组件。

// 推荐:
this.setState({comment: 'Hello'});

// 不推荐:
this.state.comment = 'hello';

2、State 的更新可能是异步的

// 推荐:
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

// 不推荐:
this.setState({
  counter: this.state.counter + this.props.increment,
});

11、状态提升

如果多个组件需要反映相同的变化数据,建议将共享状态提升到最近的共同父组件中去;从而依靠自上而下的数据流,而不是尝试在不同组件间同步 state。

12、路由加载

建议使用路由懒加载当前用户所需要的内容,这样能够显著地提高你的应用性能。尽管并没有减少应用整体的代码体积,但你可以避免加载用户永远不需要的代码,并在初始加载的时候减少所需加载的代码量。

// 推荐:
const OtherComponent = React.lazy(() => import('./OtherComponent'));


// 不推荐:
import OtherComponent from './OtherComponent';

13、Axios发起请求时机

componentDidMount这个生命周期发起请求比较合理

14、推荐使用 Context

如果某个属性在组件树的不同层级的组件之间需要用到,我们应该使用 Context 提供在组件之间共享此属性的方式,而不不是显式地通过组件树的逐层传递 props。