1. 程式人生 > >React元件開發總結

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演算法。