React元件開發總結
1、有狀態元件和無狀態元件
其實換言之就是需不需要一套react的生命週期來維護這一套狀態,有時候我們提出一個子元件來,但是這個子元件除了render出來一虛擬dom結構,並沒有任何狀態,所以是沒必要提出來做一個單獨的元件,哪怕是想複用。這個時候就用到了無狀態元件,即一個無狀態函式,這樣在渲染的時候,就省去了子元件生命週期的維護和執行,避免了不必要的檢查和記憶體分配,做到了內部優化。
class App extends React.Component{ constructor(props){ super(props); this.state = {} } render(){ return <div>aaaa</div> } }
典型的無狀態無生命週期元件,所以說不管複用也好,拆分也好,這種無狀態無週期元件寫成一個無狀態函式最完美。
renderapp = ()=>{ render(){ return <div>aaaa</div. } }
2、高階元件的使用。
高階函式
setFristName = ()=>{ this.setState({visible:false}) console.log('setFristName') } setLastName = ()=>{ this.setState({visible:false}) console.log('setLastName') }
這兩個函式this.setState({visible:false})是共有的思維,
可以做一箇中間函式專門處理提取公有的邏輯
setFristName = ()=>{ let {name} = this.state this.setState({visible:false}) console.log('setFristName',name) } setLastName = ()=>{ let {name} = this.state this.setState({visible:false}) console.log('setLastName',name) } commonConpute = (wrappedFunc)=>{ let newFunc = () => { let {name} = this.state this.setState({visible:false}) wrappedFunc(name); } return newFunc; } commonConpute(setFristName)(); commonConpute(setLastName)()
高階元件的使用就是類似於高階函式的思想來建立一箇中間函式,做函式傳遞
import React, {Component} from 'react' CommonConpute = (SetLastName) => { class NewCommonComponent extends Component { constructor(props) { super(props); this.state = { name: '' } } componentWillMount() { let name = localStorage.getItem('name'); this.setState({name}) } render() { return <SetLastName username={this.state.username} /> } } return NewCommonComponent } export default CommonConpute
a = ()=>{
class 類
return 類名
}
export default a;
所謂的高階元件,其實就是高階函式對容易的封裝。引數就是子元件。
import React, {Component} from 'react'; import CommonConpute from 'commonConpute.js'; class SetLastName extends Component { render() { return ( <div>welcome {this.props.username}</div> ) } } export default CommonConpute(SetLastName);
高階元件就是用一個高階函式把子元件當作引數傳遞給目標元件了。
目標元件使用子元件的時候把name 通過 props 傳遞給子元件了。
子元件只管從 props裡面拿來用就好了。
3、元件模組化思想
使用React時,元件或容器的程式碼在根本上必須只負責一塊UI功能。不管是無狀態元件函式,還是有狀態元件模組,都應該是負責ui介面的一整塊的功能。所以在劃分元件和拆分的時候一定要規劃好。
不規範展示Viw
1
<div> <Header/> <ul> { this.state.schoolList.splice(0,2) .map((item,index)=>{ return <li key={index}> {item.schoolName} </li> }) } { this.state.schoolList.splice(2,4) .map((item,index)=>{ return <li key={index}> {item.schoolName} </li> }) } </ul> <Footer/> </div>
中間UI中的列表這裡,有兩個{}表示式分隔開了本該是一個元件。
分割不合理,而且this.state.schoolList.splice計算也是重複的擷取。
{ this.state.schoolList.map((item,index)=>{ return ( <li key={index}> {item.schoolName} </li> {index == 1 ? <br/> : null} ) }) }
寫到現在,其實心得有些分享一下:
如果元件根本不需要狀態,那麼就使用函式定義的無狀態元件,即函式
傳遞元件所需要的屬性。只有當屬性列表太長時,才使用{…this.props}進行傳遞。我曾經有段時間非常喜歡這樣不太合適的寫法:
class App extends React.Component{ constructor(props){ super(props); this.state = { ...props } } }
這樣其實很容易造成state命名重複,很難維護和開發。所以傳遞的時候儘量傳遞需要的,
如果元件裡面有太多的判斷邏輯(if-else語句)通常意味著這個元件需要被拆分成更細的元件或模組。
模組類命名,方法命名,變數命名儘量團隊統一,保持統一風格,簡明扼要,見名之意,有助於元件複用和元件維護。
註釋,要不就別加,真的,要麼整個團隊要保持良好習慣,加的話,每次的迭代更新就要更改註釋。最好,明白清楚,簡要。團隊風格統一。不要誤導,千萬不要誤導。
在shouldComponentUpdate中檢查更新,是否重新render的時候,判斷一定要精確,避免不必要的render,重paint,diff演算法也是很耗費效能的。
4、元件開發注意點
三元函式元件判斷渲染,最多一層,再多的用if-elseif-else來吧,因為複雜點的三目運算可讀性很差
isTrue ? {}:isShow ? {} : {} 不可取,可讀性非常差
1
如果元件需要三木運算子
{ isTrue ? <App/> : isShow ? <App1/> : <App2/> }
最佳的解決方案:
將邏輯移到無狀態元件內部,不同條件的時候return不同的元件。
這樣做的好處就是把UI結構和邏輯層分開。
return ( {this.renderApp} ) renderApp = ()=>{ if(isTrue){ return <App/> }else{ if(isShow){ return <App1/> }else{ return <App2/> } } }
setState合併為一次更新
在無狀態函式裡最好執行完畢以後一次性的setState
setModalVisible = ()=>{ this.setState({data:[1,2,3]}) ..... this.setState({arr:[2,3]}) }
將多次state更新合
併成一次更新。避免觸發多次render,耗費diff效能。
大家都知道setState是非同步更新,可以在回撥函式中拿到最新的state 值,所以setState非同步執行所花費的時間完全取決於irtual DOM的 diff演算法。