Skip to content

Latest commit

 

History

History
469 lines (377 loc) · 15.4 KB

File metadata and controls

469 lines (377 loc) · 15.4 KB

Airbnb React/JSX Style Guide

A mostly reasonable approach to React and JSX 用更合理的方式书写React和JSX

Table of Contents

目录

  1. Basic Rules
  2. 基本规则
  3. Class vs React.createClass vs stateless
  4. Class vs React.createClass vs stateless
  5. Naming
  6. 命名
  7. Declaration
  8. 声明
  9. Alignment
  10. 对齐
  11. Quotes
  12. 引号
  13. Spacing
  14. 空格
  15. Props
  16. 属性
  17. Parentheses
  18. 大括号
  19. Tags
  20. 标签
  21. Methods
  22. 方法
  23. Ordering
  24. 排序
  25. isMounted
  26. isMounted

Basic Rules

基本规则

  • Only include one React component per file.

  • Always use JSX syntax.

  • Do not use React.createElement unless you're initializing the app from a file that is not JSX.

  • 每个文件只包含一个React组件;

  • 始终使用 JSX 语法;

  • 不要使用 React.createElement方法,除非初始化 app 的文件不是 JSX 格式。

Class vs React.createClass vs stateless

  • If you have internal state and/or refs, prefer class extends React.Component over React.createClass unless you have a very good reason to use mixins. eslint: react/prefer-es6-class

  • 如果组件拥有内部的 state 或者 refs 的时,更推荐使用 class extends React.Component,除非你有一个非常好的理由要使用 mixin。 eslint: react/prefer-es6-class

    // bad
    const Listing = React.createClass({
      // ...
      render() {
        return <div>{this.state.hello}</div>;
      }
    });
    
    // good
    class Listing extends React.Component {
      // ...
      render() {
        return <div>{this.state.hello}</div>;
      }
    }

    And if you don't have state or refs, prefer normal functions (not arrow functions) over classes: 如果没有组件没有内部 state 或者 refs,那么普通函数 (不要使用箭头函数) 比类的写法更好:

    // bad
    class Listing extends React.Component {
      render() {
        return <div>{this.props.hello}</div>;
      }
    }
    
    // bad (since arrow functions do not have a "name" property)
    // bad (因为箭头函数没有“name”属性)
    const Listing = ({ hello }) => (
      <div>{hello}</div>
    );
    
    // good
    function Listing({ hello }) {
      return <div>{hello}</div>;
    }

Naming

命名

  • Extensions: Use .jsx extension for React components.

  • Filename: Use PascalCase for filenames. E.g., ReservationCard.jsx.

  • Reference Naming: Use PascalCase for React components and camelCase for their instances. eslint: react/jsx-pascal-case

  • 扩展名:React 组件使用.jsx扩展名;

  • 文件名:文件名使用帕斯卡命名。 例如: ReservationCard.jsx

  • 引用命名:React 组件使用帕斯卡命名,引用实例采用骆驼命名。 eslint: react/jsx-pascal-case

    // bad
    import reservationCard from './ReservationCard';
    
    // good
    import ReservationCard from './ReservationCard';
    
    // bad
    const ReservationItem = <ReservationCard />;
    
    // good
    const reservationItem = <ReservationCard />;
  • Component Naming: Use the filename as the component name. For example, ReservationCard.jsx should have a reference name of ReservationCard. However, for root components of a directory, use index.jsx as the filename and use the directory name as the component name:

  • 组件命名:组件名称应该和文件名一致, 例如: ReservationCard.jsx 应该有一个ReservationCard的引用名称。 但是, 如果是在目录中的组件, 应该使用 index.jsx 作为文件名 并且使用文件夹名称作为组件名:

    // bad
    import Footer from './Footer/Footer';
    
    // bad
    import Footer from './Footer/index';
    
    // good
    import Footer from './Footer';

Declaration

声明

  • Do not use displayName for naming components. Instead, name the component by reference.
  • 不要使用`displayName`属性来命名组件,应该使用类的引用名称。
    // bad
    export default React.createClass({
      displayName: 'ReservationCard',
      // stuff goes here
    });
    
    // good
    export default class ReservationCard extends React.Component {
    }

Alignment

对齐

  • Follow these alignment styles for JSX syntax. eslint: react/jsx-closing-bracket-location

  • 为 JSX 语法使用下列的对其方式。eslint: react/jsx-closing-bracket-location

    // bad
    <Foo superLongParam="bar"
         anotherSuperLongParam="baz" />
    
    // good
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    />
    
    // if props fit in one line then keep it on the same line
    // 如果组件的属性可以放在一行就保持在当前一行中
    <Foo bar="bar" />
    
    // 多行属性采用缩进
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    >
      <Quux />
    </Foo>

Quotes

引号

  • Always use double quotes (") for JSX attributes, but single quotes for all other JS. eslint: jsx-quotes
  • JSX 的属性都采用双引号,其他的 JS 都使用单引号。eslint: jsx-quotes

Why? JSX attributes can't contain escaped quotes, so double quotes make conjunctions like "don't" easier to type.

为什么这样做?JSX 属性 不能包含转义的引号, 所以当输入"don't"这类的缩写的时候用双引号会更方便。

Regular HTML attributes also typically use double quotes instead of single, so JSX attributes mirror this convention.

标准的 HTML 属性通常也会使用双引号,所以 JSX 属性也会遵守这样的约定。

```javascript
// bad
<Foo bar='bar' />

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

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

// good
<Foo style={{ left: '20px' }} />
```

Spacing

空格

  • Always include a single space in your self-closing tag.
  • 终始在自闭合标签前面添加一个空格。
    // bad
    <Foo/>
    
    // very bad
    <Foo                 />
    
    // bad
    <Foo
     />
    
    // good
    <Foo />

Props

属性

  • Always use camelCase for prop names.

  • 属性名称始终使用骆驼命名法。

    // bad
    <Foo
      UserName="hello"
      phone_number={12345678}
    />
    
    // good
    <Foo
      userName="hello"
      phoneNumber={12345678}
    />
  • Omit the value of the prop when it is explicitly true. eslint: react/jsx-boolean-value

  • 当属性值等于true的时候,省略该属性的赋值。 eslint: react/jsx-boolean-value

    // bad
    <Foo
      hidden={true}
    />
    
    // good
    <Foo
      hidden
    />

Parentheses

大括号

  • Wrap JSX tags in parentheses when they span more than one line. eslint: react/wrap-multilines

  • 用括号包裹多行 JSX 标签。 eslint: react/wrap-multilines

    // bad
    render() {
      return <MyComponent className="long body" foo="bar">
               <MyChild />
             </MyComponent>;
    }
    
    // good
    render() {
      return (
        <MyComponent className="long body" foo="bar">
          <MyChild />
        </MyComponent>
      );
    }
    
    // good, when single line
    render() {
      const body = <div>hello</div>;
      return <MyComponent>{body}</MyComponent>;
    }

Tags

标签

Methods

方法

  • Bind event handlers for the render method in the constructor. eslint: react/jsx-no-bind
  • 在 render 方法中事件的回调函数,应该在构造函数中进行bind绑定。 eslint: react/jsx-no-bind

Why? A bind call in the render path creates a brand new function on every single render.

为什么这样做? 在 render 方法中的 bind 调用每次调用 render 的时候都会创建一个全新的函数。

```javascript
// bad
class extends React.Component {
  onClickDiv() {
    // do stuff
  }

  render() {
    return <div onClick={this.onClickDiv.bind(this)} />
  }
}

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

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

  onClickDiv() {
    // do stuff
  }

  render() {
    return <div onClick={this.onClickDiv} />
  }
}
```
  • Do not use underscore prefix for internal methods of a React component.
  • React 组件的内部方法命名不要使用下划线前缀。
    // bad
    React.createClass({
      _onClickSubmit() {
        // do stuff
      },
    
      // other stuff
    });
    
    // good
    class extends React.Component {
      onClickSubmit() {
        // do stuff
      }
    
      // other stuff
    }

Ordering

排序

  • Ordering for class extends React.Component:
  • class extends React.Component的顺序:
  1. static静态方法
  2. constructor
  3. getChildContext
  4. componentWillMount
  5. componentDidMount
  6. componentWillReceiveProps
  7. shouldComponentUpdate
  8. componentWillUpdate
  9. componentDidUpdate
  10. componentWillUnmount
  11. 点击回调或者事件回调 比如 onClickSubmit() 或者 onChangeDescription()
  12. render函数中的 getter 方法 比如 getSelectReason() 或者 getFooterContent()
  13. 可选的 render 方法 比如 renderNavigation() 或者 renderProfilePicture()
  14. render
  • How to define propTypes, defaultProps, contextTypes, etc...

  • 怎样定义 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;
  • Ordering for React.createClass: eslint: react/sort-comp

  • React.createClass的排序:eslint: react/sort-comp

  1. displayName
  2. propTypes
  3. contextTypes
  4. childContextTypes
  5. mixins
  6. statics
  7. defaultProps
  8. getDefaultProps
  9. getInitialState
  10. getChildContext
  11. componentWillMount
  12. componentDidMount
  13. componentWillReceiveProps
  14. shouldComponentUpdate
  15. componentWillUpdate
  16. componentDidUpdate
  17. componentWillUnmount
  18. clickHandlers or eventHandlers like onClickSubmit() or onChangeDescription()
  19. getter methods for render like getSelectReason() or getFooterContent()
  20. Optional render methods like renderNavigation() or renderProfilePicture()
  21. 点击回调或者事件回调 比如 onClickSubmit() 或者 onChangeDescription()
  22. render函数中的 getter 方法 比如 getSelectReason() 或者 getFooterContent()
  23. 可选的 render 方法 比如 renderNavigation() 或者 renderProfilePicture()
  24. render

isMounted

Why? [isMounted is an anti-pattern][anti-pattern], is not available when using ES6 classes, and is on its way to being officially deprecated. 为什么这样做? isMounted是一种反模式,当使用 ES6 类风格声明 React 组件时该属性不可用,并且即将被官方弃用。

⬆ back to top