一個良好的代碼規范,不僅能提升web性能,提高團隊協作,還便于后期維護,拓展。
“代碼即文檔”是我們對規范的一個愿景。下面就基于ES6的React項目配置,談幾點對React組件規范的幾點建議。
我們的組件分為兩大類,UI組件和container組件。
UI組件
UI組件是構成前端界面的基礎單元,它們不涉及業務邏輯,無生命周期函數,只負責單純的渲染,所有數據都通過 props 傳入。
一, 咱們的UI組件大致分為兩種情況,無狀態和有狀態
- 如果是無狀態組件,則使用純函數,我們大部分的UI組件都是這種純函數。
import React, {PropTypes} from 'react'
import {connect} from 'react-redux'
const dataType = {
onExpand: PropTypes.func.isRequired,
isOpen: PropTypes.bool
}
const List = ({ onExpand, expanded = false, childred }) =>
<form style={ expanded ? { height: 'auto' } : { height: 0 } }>
{children}
<button onClick={onExpand}>Expand</button>
</form>;
List.propTypes = dataType
export default connect(List)
- 如果是有狀態組件(這里的狀態,只是負責UI自身的狀態),則使用 React 的 PureComponent
import React, {PureComponent, PropTypes} from 'react'
import {connect} from 'react-redux'
@connect(...)
export default class Listing extends PureComponent {
static propTypes = {
model: PropTypes.object.isRequired,
title: PropTypes.string
}
static defaultProps = {
model: {id:0},
title: 'minooo'
}
state = {
isOpen: false
};
onOpen = () => {
this.setState((preState, props) => ({isOpen: !preState.isOpen}))
}
render(){
const {focus} = this.state;
...
}
}
二, 一般在有狀態組件中可能需要定義一些方法,這些方法使用箭頭函數,以此避免render中的this綁定帶來的性能損耗。
// bad
export default class Listing extends PureComponent {
//...
onClick () {
...
};
render(){
return(
<div onClick={this.onClick.bind(this)}>...</div>
)
}
}
// good
export default class Listing extends PureComponent {
//...
onClick = () => {
...
};
render(){
return(
<div onClick={this.onClick}>...</div>
)
}
}
三, 如果閉合標簽內無子節點,則寫為單標簽
// bad
<i className="i-left"></i>
// good
<i className="i-left" />
四, 為了讓便于閱讀,請給代碼合理的間隔,換行,讓我們的代碼像詩一樣干凈利索,一目了然。
// bad
const Course = ({address, tel, onClick}) =>
<div className="bg-white pad2 overflow-h">
<a href="javascript:;" className="ui-border-r inblock pr10" onClick={onClick}>
<i className={"i-zuobiao32 main-color font-size-16 fl mr5 "+styles.icon}></i>
<span className={"text-overflow-1 " +styles.address}>{address}</span>
</a>
<a href={"tel: "+tel}><i className={"i-dianhua32 main-color font-size-16 fr "+styles.icon}></i></a
</div>;
// good
const Course = ({address, tel, onClick}) =>
<div className="bg-white pad2 overflow-h">
<a
href="javascript:;"
className="ui-border-r inblock pr10"
onClick={onClick}
>
<i className={`i-zuobiao32 main-color font-size-16 fl mr5 ${styles.icon}`} />
<span className={"text-overflow-1 " + styles.address}>{address}</span>
</a>
<a href={"tel: " + tel}>
<i className={"i-dianhua32 main-color font-size-16 fr " + styles.icon} />
</a>
</div>;
五,盡量避免使用數組的索引作為key的屬性值,推薦使用指定的ID,原因?
// bad
{todos.map((todo, index) =>
<Todo
{...todo}
key={index}
/>
)}
// good
{todos.map(todo => (
<Todo
{...todo}
key={todo.id}
/>
))}
六,使用 ref 回調函數,官方ref
// bad
<Foo
ref="myRef"
/>
// good
<Foo
ref={(ref) => { this.myRef = ref; }}
/>
七,使用箭頭函數鎖定局部變量
{props.items.map((item, index) =>
<Item
key={item.key}
// good
onClick={() => this.doSomethingWith(item.name, index)}
// bad
onClick={this.doSomething.bind(null, item.name, index)}
/>
)}