React编程规范

一、工程结构

1.1 工程目录

目前大致工程目录如下:

├─ src                         //源码
│  ├─ components               //展示组件,嵌套在容器组件中,通过props获取容器组件中的数据,负责展示和渲染
│  │  ├─ DemoComponent
│  │  │  ├─ index.tsx
│  │  │  └─ style.scss
│  │  └─ TestComponent
│  │     ├─ index.tsx
│  │     └─ style.scss
│  ├─ containers              //容器组件,负责业务流程逻辑的处理,如发送网络请求,处理请求数据
│  │  ├─ DemoContainer
│  │  │  ├─ reducer.ts        //响应action,处理并更新state
│  │  │  ├─ saga.ts           //发起http请求,分发请求之后的结果
│  │  │  ├─ action.ts         //传递数据到store
│  │  │  ├─ constant.ts       //定义事件常量
│  │  │  ├─ index.tsx
│  │  │  └─ style.scss
│  │  └─ TestContainer
│  │     ├─ reducer.ts
│  │     ├─ saga.ts
│  │     ├─ action.ts
│  │     ├─ constant.ts
│  │     ├─ index.tsx
│  │     └─ style.scss
│  ├─ images                  //存放图片资源
│  │  ├─ Common
│  │  ├─ DemoComponent
│  │  ├─ TestComponent
│  │  ├─ DemoContainer
│  │  └─ TestContainer
│  ├─ mock                    //存放静态json数据,多用于调试
│  ├─ styles                  //全局样式
│  ├─ utils                   //工具库
│  ├─ app.tsx                 //入口文件,配置store,热加载等
│  ├─ config.tsx              //api接口
│  ├─ routes.ts               //页面路由
│  ├─ reducers.ts             //合并reducer
│  ├─ sagas.ts                //合并saga
│  ├─ index.html              //入口html文件
│  └─ tsconfig.json           //TypeScript编译配置文件
├─ www
├─ .babelrc
├─ .gitignore
├─ Jenkinsfile
├─ webpack.config.js
├─ webpack.vendor.config.js
└─ package.json
复制代码

注:
1、其中components和containers文件夹中的文件夹命名规则以大驼峰式命名法(或叫Pascal命名法)为准,即每个单词采用大写字母,单词之间不以空格、连接号或底线连接。
2、images文件夹中的图片资源的命名以单词底线连接规则,如login_bg.jpg;common文件夹存放公共资源文件

1.2 文件示例

1.2.1 components中的文件
import * as React from 'react';
//props声明
interface DemoComponentProps {
    dataSource: any;
}
//state声明
interface DemoComponentState {
    isLoading: boolean;
}

export default class DemoComponent extends React.Component<DemoComponentProps, DemoComponentState> {
    construct(props: DemoComponentProps) {
        super(props);

        this.state = {
            isLoading: false
        };
    }

    render() {
        return (
            <div>123</div>
        );
    }
}
复制代码

1、组件继承于Component或PureComponent可自行调整,PureComponent能够进行数据的浅比较,减少不必要的render,提高性能,但使用了PureComponent不能再声明shouldComponentUpdate钩子函数。
2、state和props中的变量以小驼峰式命名规则为准,即小写字母开头,其他单词大写,单词之间不以空格、连接号或底线连接。

1.2.2 containers中的文件
import * as React from 'react';
import { connect } from 'react-redux';
import { getUserInfo } from './action';
//组件自身props声明,从其他组件传入的值
interface DemoComponentOwnProps {
    dataSource: any;
}
//从store传入组件的值,即进过reducer处理的值
interface DemoComponentStateProps {
    launchData?: any;
}
//发送事件的方法
interface DemoComponentDispatchProps {
    getUserInfo?: Function;
}
//state声明
interface DemoComponentState {
    isLoading: boolean;
}

//connect修饰器
@(connect<DemoComponentStateProps, DemoComponentOwnProps & DemoComponentDispatchProps, DemoComponentState>(
    (state: any) => (
        {
            launchData: state.demoReducer.launchData
        }
    ),
    (dispatch: any) => (
        {
            getUserInfo: () => {
                //多个参数使用对象形式进行传参
                dispatch(getUserInfo());
            }
        }
    )
) as any)
export default class DemoComponent extends React.Component<
  DemoComponentStateProps & DemoComponentOwnProps & DemoComponentDispatchProps,
  DemoComponentState
  > {
    construct(props: DemoComponentStateProps & DemoComponentOwnProps & DemoComponentDispatchProps) {
        super(props);

        this.state = {
            isLoading: false
        };
    }

    render() {
        return (
            <div>123</div>
        );
    }
}
复制代码

1、组件继承于Component或PureComponent可自行调整,PureComponent能够进行数据的浅比较,减少不必要的render,提高性能,但使用了PureComponent不能再声明shouldComponentUpdate钩子函数。
2、state和props中的变量以小驼峰式命名规则为准,即小写字母开头,其他单词大写,单词之间不以空格、连接号或底线连接。
3、constant以全大写为主,单词之间以底线连接,如:

export const SHOW_MODAL = 'CUSTOM_MODAL/SHOW_MODAL'
复制代码

4、其他文件的变量命名以小驼峰式命名为准。

1.3 React代码规范

1.3.1 基本代码风格
  • 代码缩进
//能在一行显示时,结尾空格分隔
<Foo bar="bar" baz="baz" />

//bad,不能在一行显示时
<Foo bar="bar" baz="baz" ... />

//good
<Foo 
  bar="bar"
  baz="baz"
  ...
/>
复制代码
  • 双引号使用
//bad
<Foo bar='bar' />

//good
<Foo bar="bar" />

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

//good
<Foo style={{ left: '20px' }} />
复制代码
  • 总是使用回调函数方式定义ref
//bad,这样定义就会弱化语法类型,如:单词写错了对应不上不会报错提示
<Foo ref="myRef" />

//good
<Foo ref={ref => this.myRef = ref} />
复制代码
  • 将多行JSX标签写在()
//bad
render() {
    return <MyComponent>
        <MyChild />
    </MyComponent>;
}

//good
render() {
    return (
        <MyComponent>
            <MyChild />
        </MyComponent>
    );
}

//good,单行可以不需要()
render() {
    return <MyComponent />;
}
复制代码
  • JSX map返回
render() {
    //推荐取props或state上的值通过这种方式取,不建议直接通过`this.props.`或`this.state.`取
    const { data } = this.props;
    return (
        <ul>
            {
                //若直接返回元素,无中间计算过程,无需return,使用`()`进行返回
                data.map((item: any) => (
                    <li key={item.id}>
                        {
                            //若存在计算,则通过`{}`包裹,使用return返回JSX标签
                            item.map((piece: any) => {
                                const body = <span key={piece.id}>123</span>;
                                //do something
                                return body;
                            }
                        }
                    </li>
                ))
            }
        </ul>
    )
}
复制代码
  • 方法书写规范
//bad
render() {
    return <button onClick={() => this.handleClick()}>123</button>
}

//good,当无参数时
render() {
    return <button onClick={this.handleClick}>123</button>
}

//good,但有参数时
render() {
    return <button onClick={(e) => this.handleClick(e, other)}>123</button>
}
复制代码
1.3.2 影响性能的代码风格
  • 在JSX标签中bindthis

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

//bad
class A extends React.Component {
    handleClick() {
        //do something
    }

    render() {
        return <button onClick={this.handleClick.bind(this)}>123</button>
    }
}

//good
class A extends React.Component {
    constructor(props) {
        super(props);

        this.handleClick = this.handleClick.bind(this);
    }

    handleClick() {
        //do something
    }

    render() {
        return <button onClick={this.handleClick}>123</button>
    }
}
复制代码
  • 使用const常量

因为在每次render过程中,都会新建一个新的变量,浪费资源

//bad
render() {
    return <div style={{color: 'red'}}>123</div>
}

//good
render() {
    const textColor = {color: 'red'};
    return <div style={textColor}>123</div>
}
复制代码
  • 对循环JSX标签使用key

不推荐直接使用index,最好为唯一标识

render() {
    return (
        <ul>
            {
                data.map((item: any) => (
                    <li key={item.id}>123</li>
                ))
            }
        </ul>
    )
}
复制代码
  • 少用display:none来隐藏元素

使用return null而不是CSS的display:none来控制节点的显示隐藏。保证同一时间页面的DOM节点尽可能的少

//bad
render() {
    const { isShow } = this.props;
    return (
        <div>
            <span style={{ display: isShow ? 'block' : 'none' }}>123</span>
        </div>
    )
}

//good
render() {
    const { isShow } = this.props;
    return (
        <div>
            {
                isShow &&
                <span>123</span>
            }
        </div>
    )
}
复制代码
  • 避免兜底值字面量

有时我们会在render函数中创建一个兜底的值来避免undefined报错。在这些情况下,最好在组件外创建一个兜底的常量而不是创建一个新的字面量。

//bad
render() {
    let arr = [];
    if (this.props.things) {
        arr = this.props.things;
    }

    return <Foo things={ things } />;
}
//bad
render() {
  // 这在功能上和前一个例子一样
  return <Foo things={ this.props.things || [] } />
}

//good
// 在组件外部声明
const NO_THINGS = [];

render() {
  return <Foo things={ this.props.things || NO_THINGS } />
}
复制代码
  • 不滥用{...this.props}

只传递component需要的props即可,传递的太多,或者层次传的太深,都会加重shuoldComponentUpdate其里面的数据比较负担

  • 慎用setState

与视图渲染无关的,但需存储数据的,不要放在state中,每次setState都会引起不必要的render,尽管视图并未需要更新。

转载于:https://juejin.im/post/5b7d1666f265da434c1f487c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值