來自於Airbnb React/JSX 中文編碼規範javascript
算是最合理的React/JSX編碼規範之一了html
每一個文件只寫一個模塊.java
react/no-multi-comp
.React.createElement
,除非從一個非JSX的文件中初始化你的app.Class vs React.createClass vs statelessnode
refs
, 推薦使用 class extends React.Component
而不是 React.createClass
,除非你有充足的理由來使用這些方法. react/prefer-es6-class
react/prefer-stateless-function
// 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>; } }
若是你的模塊沒有狀態或是沒有引用`refs`, 推薦使用普通函數(非箭頭函數)而不是類:
// bad class Listing extends React.Component { render() { return <div>{this.props.hello}</div>; } } // bad (relying on function name inference is discouraged) const Listing = ({ hello }) => ( <div>{hello}</div> ); // good function Listing({ hello }) { return <div>{hello}</div>; }
.jsx
擴展名.ReservationCard.jsx
. - 引用命名: React模塊名使用帕斯卡命名,實例使用駱駝式命名. eslint: react/jsx-pascal-case
react
// bad import reservationCard from './ReservationCard'; // good import ReservationCard from './ReservationCard'; // bad const ReservationItem = <ReservationCard />; // good const reservationItem = <ReservationCard />;
模塊命名: 模塊使用當前文件名同樣的名稱. 好比 ReservationCard.jsx
應該包含名爲 ReservationCard
的模塊. 可是,若是整個文件夾是一個模塊,使用 index.js
做爲入口文件,而後直接使用 index.js
或者文件夾名做爲模塊的名稱:git
// 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.es6
// bad export default function withFoo(WrappedComponent) { return function WithFoo(props) { return <WrappedComponent {...props} foo />; } } // good 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; }
爲何?對於
style
和className
這樣的屬性名,咱們都會默認它們表明一些特殊的含義,如元素的樣式,CSS class的名稱。在你的應用中使用這些屬性來表示其餘的含義會使你的代碼更難閱讀,更難維護,而且可能會引發bug。github
// bad <MyComponent style="fancy" /> // good <MyComponent variant="fancy" />
不要使用 displayName
來命名React模塊,而是使用引用來命名模塊, 如 class 名稱.設計模式
// bad export default React.createClass({ displayName: 'ReservationCard', // stuff goes here }); // good export default class ReservationCard extends React.Component { }
遵循如下的JSX語法縮進/格式. eslint: react/jsx-closing-bracket-location
數組
// bad <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // good, 有多行屬性的話, 新建一行關閉標籤 <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // 若能在一行中顯示, 直接寫成一行 <Foo bar="bar" /> // 子元素按照常規方式縮進 <Foo superLongParam="bar" anotherSuperLongParam="baz" > <Quux /> </Foo>
"
), 其餘均使用單引號('
). eslint: jsx-quotes
爲何? HTML屬性也是用雙引號, 所以JSX的屬性也遵循此約定.
// bad <Foo bar='bar' /> // good <Foo bar="bar" /> // bad <Foo style={{ left: "20px" }} /> // good <Foo style={{ left: '20px' }} />
老是在自動關閉的標籤前加一個空格,正常狀況下也不須要換行. eslint: no-multi-spaces
, react/jsx-space-before-closing
// bad <Foo/> // very bad <Foo /> // bad <Foo /> // good <Foo />
不要在JSX {}
引用括號裏兩邊加空格. eslint: react/jsx-curly-spacing
// bad <Foo bar={ baz } /> // good <Foo bar={baz} />
JSX屬性名使用駱駝式風格camelCase
.
// bad <Foo UserName="hello" phone_number={12345678} /> // good <Foo userName="hello" phoneNumber={12345678} />
若是屬性值爲 true
, 能夠直接省略. eslint: react/jsx-boolean-value
// bad <Foo hidden={true} /> // good <Foo hidden />
<img>
標籤老是添加 alt
屬性. 若是圖片以presentation(感受是以相似PPT方式顯示?)方式顯示,alt
可爲空, 或者<img>
要包含role="presentation"
. eslint: jsx-a11y/img-has-alt
// bad <img src="hello.jpg" /> // good <img src="hello.jpg" alt="Me waving hello" /> // good <img src="hello.jpg" alt="" /> // good <img src="hello.jpg" role="presentation" />
alt
值裏使用如 "image", "photo", or "picture"包括圖片含義這樣的詞, 中文也同樣. eslint: jsx-a11y/img-redundant-alt
爲何? 屏幕助讀器已經把
img
標籤標註爲圖片了, 因此沒有必要再在alt
裏說明了.
// bad <img src="hello.jpg" alt="Picture of me waving hello" /> // good <img src="hello.jpg" alt="Me waving hello" />
使用有效正確的 aria role
屬性值 ARIA roles. eslint: jsx-a11y/aria-role
// bad - not an ARIA role <div role="datepicker" /> // bad - abstract ARIA role <div role="range" /> // good <div role="button" />
accessKey
屬性. eslint: jsx-a11y/no-access-key
爲何? 屏幕助讀器在鍵盤快捷鍵與鍵盤命令時形成的不統一性會致使閱讀性更加複雜.
// bad <div accessKey="h" /> // good <div />
避免使用數組的index來做爲屬性key
的值,推薦使用惟一ID. (爲何?)
// bad {todos.map((todo, index) => <Todo {...todo} key={index} /> )} // good {todos.map(todo => ( <Todo {...todo} key={todo.id} /> ))}
defaultProps
屬性.爲何? propTypes 能夠做爲模塊的文檔說明, 而且聲明 defaultProps 的話意味着閱讀代碼的人不須要去假設一些默認值。更重要的是, 顯示的聲明默認屬性可讓你的模塊跳過屬性類型的檢查.
// bad function SFC({ foo, bar, children }) { return <div>{foo}{bar}{children}</div>; } SFC.propTypes = { foo: PropTypes.number.isRequired, bar: PropTypes.string, children: PropTypes.node, }; // good function SFC({ foo, bar }) { return <div>{foo}{bar}</div>; } SFC.propTypes = { foo: PropTypes.number.isRequired, bar: PropTypes.string, }; SFC.defaultProps = { bar: '', children: null, };
老是在Refs裏使用回調函數. eslint: react/no-string-refs
// bad <Foo ref="myRef" /> // good <Foo ref={(ref) => { this.myRef = ref; }} />
將多行的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, 單行能夠不須要 render() { const body = <div>hello</div>; return <MyComponent>{body}</MyComponent>; }
對於沒有子元素的標籤來講老是本身關閉標籤. eslint: react/self-closing-comp
// bad <Foo className="stuff"></Foo> // good <Foo className="stuff" />
若是模塊有多行的屬性, 關閉標籤時新建一行. eslint: react/jsx-closing-bracket-location
// bad <Foo bar="bar" baz="baz" /> // good <Foo bar="bar" baz="baz" />
使用箭頭函數來獲取本地變量.
function ItemList(props) { return ( <ul> {props.items.map((item, index) => ( <Item key={item.key} onClick={() => doSomethingWith(item.name, index)} /> ))} </ul> ); }
render()
裏使用事件處理方法時,提早在構造函數裏把 this
綁定上去. eslint: react/jsx-no-bind
爲何? 在每次
render
過程當中, 再調用bind
都會新建一個新的函數,浪費資源.
// 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} /> } }
_
前綴,本質上它並非私有的.爲何?
_
下劃線前綴在某些語言中一般被用來表示私有變量或者函數。可是不像其餘的一些語言,在JS中沒有原生支持所謂的私有變量,全部的變量函數都是共有的。儘管你的意圖是使它私有化,在以前加上下劃線並不會使這些變量私有化,而且全部的屬性(包括有下劃線前綴及沒有前綴的)都應該被視爲是共有的。瞭解更多詳情請查看Issue #1024, 和 #490 。
// bad React.createClass({ _onClickSubmit() { // do stuff }, // other stuff }); // good class extends React.Component { onClickSubmit() { // do stuff } // other stuff }
在 render
方法中老是確保 return
返回值. eslint: react/require-render-return
// bad render() { (<div />); } // good render() { return (<div />); }
class extends React.Component
的生命週期函數:static
方法constructor
構造函數getChildContext
獲取子元素內容componentWillMount
模塊渲染前componentDidMount
模塊渲染後componentWillReceiveProps
模塊將接受新的數據shouldComponentUpdate
判斷模塊需不須要從新渲染componentWillUpdate
上面的方法返回 true
, 模塊將從新渲染componentDidUpdate
模塊渲染結束componentWillUnmount
模塊將從DOM中清除, 作一些清理任務onClickSubmit()
或 onChangeDescription()
render
裏的 getter 方法 如 getSelectReason()
或 getFooterContent()
renderNavigation()
或 renderProfilePicture()
render
render() 方法如何定義 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;
React.createClass
的生命週期函數,與使用class稍有不一樣: eslint: react/sort-comp
displayName
設定模塊名稱propTypes
設置屬性的類型contextTypes
設置上下文類型childContextTypes
設置子元素上下文類型mixins
添加一些mixinsstatics
defaultProps
設置默認的屬性值getDefaultProps
獲取默認屬性值getInitialState
或者初始狀態getChildContext
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
onClickSubmit()
or onChangeDescription()
render
like getSelectReason()
or getFooterContent()
renderNavigation()
or renderProfilePicture()
render
isMounted
. eslint: react/no-is-mounted
爲何?
isMounted
反人類設計模式:(), 在 ES6 classes 中沒法使用, 官方將在將來的版本里刪除此方法.