基础规则 每个文件只应包含一个有状态 的组件。 每个文件只包含一个组件,如有需要,该文件还可以包含多个无状态的纯组件。
使用JSX 书写组件,如非必要,禁止使用 React.createElement
。
类组件 State 不要直接修改 state 除了 state 初始化外,其它地方修改 state,需要使用 setState()
方法,直接赋值 state 不会触发组件的渲染。
this .setState({comment : 'Hello' });this .state.comment = 'hello' ;
Methods 函数 当在 render()
里使用事件处理方法时,提前在构造函数里把 this
绑定上去,或者使用箭头函数。
class extends React .Component { onClickDiv ( ) { } render ( ) { return <div onClick ={this.onClickDiv.bind(this)} /> ; } } class extends React .Component { constructor (props ) { super (props); this .onClickDiv = this .onClickDiv.bind(this ); } onClickDiv ( ) { } render ( ) { return <div onClick ={this.onClickDiv} /> ; } } class extends React .Component { onClickDiv : () => { } render ( ) { return <div onClick ={this.onClickDiv} /> ; } }
在React模块中,不要给所谓的私有函数添加 _
前缀,如果在 typescript 可以使用 private
关键字。
React.createClass({ _onClickSubmit ( ) { }, }); class extends React .Component { private onClickSubmit ( ) { } }
在 render
方法中总是确保 return
有返回值.
render ( ) { (<div /> ); } render ( ) { return (<div /> ); }
异步请求 通常在 componentDidMount
这个生命周期函数中发起异步请求。
componentDidMount ( ) { loadData().then(res => { this .setState({ data : res.data }); }); }
计算属性/复合属性 如果有用到复杂的计算属性,可以使用 getter,不要使用计算函数:
getComputedValue ( ) { return this .state.value1 + this .state.value2; } get computedValue () { return this .state.value1 + this .state.value2; }
渲染函数 复杂的条件逻辑,使用一个函数渲染,使用函数渲染时需要以 render
开头。
{someConditional ? ( <Bar superLongParam ="bar" anotherSuperLongParam ="baz" /> ) : ( anotherOneConditional ? ( <Tee superLongParam ="bar" anotherSuperLongParam ="baz" /> ) : ( <Bee superLongParam ="bar" anotherSuperLongParam ="baz" /> ) ) } renderText ( ) { if (someConditional) { return ( <Bar superLongParam ="bar" anotherSuperLongParam ="baz" /> ); } if (anotherOneConditional) { return ( <Tee superLongParam ="bar" anotherSuperLongParam ="baz" /> ); } return ( <Bee superLongParam ="bar" anotherSuperLongParam ="baz" /> ); }
禁止使用 componentWillMount、 componentWillReceiveProps 和 componentWillUpdate React v16 废弃了这三个方法,具体原因参考:Update on Async Rendering
禁止使用 Mixins Mixins Considered Harmful
组件属性书写排序
class extends React.Component
的生命周期函数:
可选的 static
方法
private
属性
constructor
构造函数
getter
如 get selectReason()
或 get footerContent()
getChildContext
获取子元素内容
componentDidMount
模块渲染后
shouldComponentUpdate
判断模块需不需要重新渲染
componentDidUpdate
模块渲染结束
componentWillUnmount
模块将从DOM中清除, 做一些清理任务
点击回调或者事件处理器 如 onClickSubmit()
或 onChangeDescription()
可选的 render 方法 如 renderNavigation()
或 renderProfilePicture()
render
render() 方法
如何定义 propTypes
, defaultProps
, contextTypes
import React from 'react' ;import PropTypes from 'prop-types' ;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;
命名规范 文件名 使用大驼峰命名法,如 ReservationCard.jsx
import reservationCard from './ReservationCard' ;import ReservationCard from './ReservationCard' ;
如果整个目录是一个组件, 使用 index.js
作为文件名, import 的时候忽略文件名:
import Footer from './Footer/Footer' ;import Footer from './Footer/index' ;import Footer from './Footer' ;
扩展名 如果文件内是一个 React 组件,则文件后缀名使用 jsx
,如果引入了 typescript 使用 tsx
ReservationCard.js ReservationCard.jsx ReservationCard.tsx
组件命名 使用大驼峰命名法,一般和文件名保持一致,避免使用 displayName
而是使用类名。
export default class extends React .Component { displayName : 'ReservationCard' , } export default class ReservationCard extends React .Component {}
高阶组件命名 生成一个新的组件时, 新组件的组件名 displayName
应该为高阶组件名和传入的组件名的组合. 例如, 高阶组件 withFoo()
, 当传入一个 Bar
组件的时候, 生成的组件名 displayName
应该为 withFoo(Bar)
。
export default function withFoo (WrappedComponent ) { return function WithFoo (props ) { return <WrappedComponent {...props } foo /> ; } } export default function withFoo (WrappedComponent ) { function WithFoo (props ) { return <WrappedComponent {...props } foo /> ; } const wrappedComponentName = WrappedComponent.displayName || WrappedComponent.name || 'Component' ; WithFoo.displayName = `withFoo(${wrappedComponentName} )` ; return WithFoo; }
Why? A component’s displayName may be used by developer tools or in error messages, and having a value that clearly expresses this relationship helps people understand what is happening.
组件的引用名 组件的实例应该使用小驼峰法命名。
const ReservationItem = <ReservationCard /> ;const reservationItem = <ReservationCard /> ;
组件的属性名 JSX属性名使用小驼峰法命名。
<Foo UserName="hello" phone_number={12345678 } /> <Foo userName ="hello" phoneNumber ={12345678} />
组件的事件监听函数 事件监听函数使用 on
或 handle
开头的小驼峰命名法。
doclick ( ) {}afterChange ( ) {}handleClick ( ) {}onClick ( ) {}handleAfterChange ( ) {}onChanged ( ) {}
渲染函数 如果一个函数返回值为要渲染的JSX 时,需要以 render
开头。
getText ( ) { return ( <Bar superLongParam ="bar" anotherSuperLongParam ="baz" /> ); } renderText ( ) { return ( <Bar superLongParam ="bar" anotherSuperLongParam ="baz" /> ); }
空格、缩进和对齐 在自关闭的标签前加一个空格。
<Foo/> <Foo /> <Foo /> <Foo />
属性能在一行中完全显示, 则可以直接写成一行,如果有多行属性的话, 新建一行编写属性,并新建一行关闭标签。
<Foo superLongParam="bar" anotherSuperLongParam="baz" /> <Foo superLongParam ="bar" anotherSuperLongParam ="baz" /> <Foo bar ="bar" />
子组件要缩进两个空格
<Foo superLongParam="bar" anotherSuperLongParam="baz" > <Quux /> </Foo>
组件在表达式中换行时,需要使用括号包裹起来
{ showButton && <Button /> } {showButton && ( <Button /> )} {showButton && <Button /> } {someReallyLongConditional && anotherLongConditional && ( <Foo superLongParam ="bar" anotherSuperLongParam ="baz" /> ) } {someConditional ? ( <Foo /> ) : ( <Foo superLongParam ="bar" anotherSuperLongParam ="baz" /> )}
对于没有子元素的标签来说总是自己关闭标签。
<Foo className="stuff" ></Foo> <Foo className ="stuff" />
Props 属性 属性值 如果属性值为 true
, 可以直接省略。
<Foo hidden={true } /> <Foo hidden />
key 避免使用数组的 index 来作为 key
属性的值。
应当使用稳定不变的 ID。(使用不稳定的 ID 会降低性能、造成组件状态出错) 。特别是当元素的顺序可能改变的情况下,不应使用数组的 index
作为 key
.
{todos.map((todo, index ) => <Todo {...todo } key ={index} /> )} {todos.map(todo => ( <Todo {...todo } key ={todo.id} /> ))}
defaultProps 对于所有非必须的属性,总是定义defaultProps
属性.
function SFC ({ foo, bar, children } ) { return <div > {foo}{bar}{children}</div > ; } SFC.propTypes = { foo : PropTypes.number.isRequired, bar : PropTypes.string, children : PropTypes.node, }; function SFC ({ foo, bar, children } ) { return <div > {foo}{bar}{children}</div > ; } SFC.propTypes = { foo : PropTypes.number.isRequired, bar : PropTypes.string, children : PropTypes.node, }; SFC.defaultProps = { bar : '' , children : null , };
Refs 总是在Refs里使用回调函数
<Foo ref="myRef" /> <Foo ref ={(ref) => { this.myRef = ref; }}/>
说明 本规范主要参考 airbnb 的标准,并结合以前的 React 开发经验和 React 的版本迭代改变做了大量修改整理而成。