# React/JSX 规范指南 *算是最合理的 React/JSX 编码规范之一了* ## 内容目录 1. [基本规范](#basic-rules-基本规范) 1. [Class vs React.createClass vs stateless](#创建模块) 1. [命名](#naming-命名) 1. [声明模块](#declaration-声明模块) 1. [代码对齐](#alignment-代码对齐) 1. [单引号还是双引号](#quotes-单引号还是双引号) 1. [空格](#spacing-空格) 1. [属性](#props-属性) 1. [Refs引用](#refs) 1. [括号](#parentheses-括号) 1. [标签](#tags-标签) 1. [函数/方法](#methods-函数) 1. [模块生命周期](#ordering-react-模块生命周期) 1. [isMounted](#ismounted) ## Basic Rules 基本规范 - 每个文件只写一个模块. - 但是多个[无状态模块](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions)可以放在单个文件中. eslint: [`react/no-multi-comp`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md#ignorestateless). - 推荐使用JSX语法. - 不要使用 `React.createElement`,除非从一个非JSX的文件中初始化你的app. ## 创建模块 Class vs React.createClass vs stateless - 如果你的模块有内部状态或者是`refs`, 推荐使用 `class extends React.Component` 而不是 `React.createClass` ,除非你有充足的理由来使用这些方法. eslint: [`react/prefer-es6-class`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md) [`react/prefer-stateless-function`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md) ```jsx // bad const Listing = React.createClass({ // ... render() { return
{this.state.hello}
; } }); // good class Listing extends React.Component { // ... render() { return
{this.state.hello}
; } } ``` 如果你的模块没有状态或是没有引用`refs`, 推荐使用普通函数(非箭头函数)而不是类: ```jsx // bad class Listing extends React.Component { render() { return
{this.props.hello}
; } } // bad (relying on function name inference is discouraged) const Listing = ({ hello }) => (
{hello}
); // good function Listing({ hello }) { return
{hello}
; } ``` ## Naming 命名 - **扩展名**: React模块使用 `.jsx` 扩展名. - **文件名**: 文件名使用驼峰式. 如, `ReservationCard.jsx`. - **引用命名**: React模块名使用驼峰式命名,实例使用骆驼式命名. eslint: [`react/jsx-pascal-case`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md) ```jsx // bad import reservationCard from './ReservationCard'; // good import ReservationCard from './ReservationCard'; // bad const ReservationItem = ; // good const reservationItem = ; ``` - **模块命名**: 模块使用当前文件名一样的名称. 比如 `ReservationCard.jsx` 应该包含名为 `ReservationCard`的模块. 但是,如果整个文件夹是一个模块,使用 `index.js`作为入口文件,然后直接使用 `index.js` 或者文件夹名作为模块的名称: ```jsx // bad import Footer from './Footer/Footer'; // bad import Footer from './Footer/index'; // good import Footer from './Footer'; ``` - **高阶模块命名**: 对于生成一个新的模块,其中的模块名 `displayName` 应该为高阶模块名和传入模块名的组合. 例如, 高阶模块 `withFoo()`, 当传入一个 `Bar` 模块的时候, 生成的模块名 `displayName` 应该为 `withFoo(Bar)`. > 为什么?一个模块的 `displayName` 可能会在开发者工具或者错误信息中使用到,因此有一个能清楚的表达这层关系的值能帮助我们更好的理解模块发生了什么,更好的Debug. ```jsx // bad export default function withFoo(WrappedComponent) { return function WithFoo(props) { return ; } } // good export default function withFoo(WrappedComponent) { function WithFoo(props) { return ; } const wrappedComponentName = WrappedComponent.displayName || WrappedComponent.name || 'Component'; WithFoo.displayName = `withFoo(${wrappedComponentName})`; return WithFoo; } ``` ## Declaration 声明模块 - 不要使用 `displayName` 来命名React模块,而是使用引用来命名模块, 如 class 名称. ```jsx // bad export default React.createClass({ displayName: 'ReservationCard', // stuff goes here }); // good export default class ReservationCard extends React.Component { } ``` ## Alignment 代码对齐 - 遵循以下的JSX语法缩进/格式. eslint: [`react/jsx-closing-bracket-location`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md) ```jsx // bad // good, 有多行属性的话, 新建一行关闭标签 // 若能在一行中显示, 直接写成一行 // 子元素按照常规方式缩进 ``` ## Quotes 单引号还是双引号 - 对于JSX属性值总是使用双引号(`"`), 其他均使用单引号. eslint: [`jsx-quotes`](http://eslint.org/docs/rules/jsx-quotes) > 为什么? JSX属性 [不能包括转译的引号](http://eslint.org/docs/rules/jsx-quotes), 因此在双引号里包括像 `"don't"` 的属性值更容易输入. > HTML属性也是用双引号,所以JSX属性也遵循同样的语法. ```jsx // bad // good // bad // good ``` ## Spacing 空格 - 总是在自动关闭的标签前加一个空格,正常情况下也不需要换行. ```jsx // bad // very bad // bad // good ``` - 不要在JSX `{}` 引用括号里两边加空格. eslint: [`react/jsx-curly-spacing`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md) ```jsx // bad // good ``` ## Props 属性 - JSX属性名使用骆驼式风格`camelCase`. ```jsx // bad // good ``` - 如果属性值为 `true`, 可以直接省略. eslint: [`react/jsx-boolean-value`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md) ```jsx // bad