React學習-- React原始碼(3)生命週期的管理藝術
React的主要思想是通過構建可複用元件來構建使用者介面。
元件:其實就是有限狀態機,通過狀態渲染對應的介面,且每個元件都有自己的生命週期,它規定了元件的狀態和方法需要在那個階段改變和執行。
例如:某個元件有顯示和隱藏兩個狀態,在React中,只需要設定狀態setState({ showed: true/false })就可以實現顯示和隱藏的切換。
React生命週期基礎
1、當首次掛載元件時,順序執行:getDefaultProps,getInitialState,componentWillMount,render,componentDidMount 。
2、當解除安裝元件時,執行componentWillUnmount。
3、當重新掛在元件的時,按順序執行:getInitialState,componentWillMount,render,componentDidMount。但是不執行getDefaultProps
4、當再次渲染元件時,元件接收到更新狀態,此時按順序執行:componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate。
如果開發者使用ES6 classes的方法構建React元件,那麼defaultProps={}其實就是呼叫內部的getDefaultProps方法,this.state = {}其實就是呼叫getInitialState方法。
React生命週期進階
自定義元件的生命週期主要通過三個階段進行管理:MOUNTING、RECEIVE_PROPS、UNMOUNTING,它們負責通知元件當前所處的階段,應該執行生命週期中的哪個步驟。這三個階段對應三種方法:mountComponent、updateComponent、unmountComponent。在每個方法中,都提供了集中處理方法,其中前置will的在進入狀態前呼叫,字首did的在進入狀態之後呼叫。
1、建立自定義元件
createClass時建立自定義元件的入口方法。該方法在整個生命週期中只會執行一次。這個方法負責管理生命週期中的getDefaultProps,因此這個方法也將只執行一次。
2、階段一:MOUNTING
mountComponent負責管理生命週期中的方法:getInitialState、componentWillMount、render、componentDidMount。
通過mountComponent掛載元件,初始化序號、標記等引數,判斷是否為無狀態元件,並進行初始化工作,比如初始化props、context等引數。利用getInitialState獲取初始化state、初始化更新佇列和更新狀態。
如果元件中存在componentWillMount,則執行。如果在componentWillMount中呼叫了setState方法,則會進行state合併,而不是re-render。並且,inst.state = this._processPendingState (inst.props, inst.context) 方法是在componentWillMount之後執行的,因此componentWillMount方法中的state並不是最新的。
渲染完成後,若存在componentDidMount則呼叫。
如果元件存在子元件,那麼父元件的componentWillMount在子元件的componentWillMount之前呼叫;父元件的componentDidMount在子元件的componentDidMount之後呼叫(因為mountComponent是通過遞迴渲染內容的)。
3、階段二:RECEIVE_PROPS
updateComponent負責管理生命週期中的:componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate。
若存在componentWillReceiveProps,則執行。如果此時在componentWillReceiveProps中呼叫setState,是不會觸發re-render的,而是會進行state合併。並且,在componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate中也還是無法獲取到更新後的 this.state,只有在render、componentDidUpdate中才能獲取到更新後的this.state。
注意,禁止在shouldComponentUpdate和componentWillUpdate中呼叫setstate,這會造成迴圈呼叫,直至耗光瀏覽器記憶體後崩潰。
4、階段三:UNMOUNTING
unmountComponent負責管理生命週期中的unmountComponent。
如果存在unmountComponent,則執行並重置所有相關引數,更新佇列和狀態,如果此時在unmountComponent中呼叫setState,是不會觸發re-render的。
生命週期和狀態讓React元件非常靈活和強大,但是同時可能也會導致元件變的複雜而難以維護。
在實際的專案中,我們經常需要編寫一些自身沒有狀態,只是從父元件接收props,並根據這些props進行渲染的簡單元件。
在React中,一個很重要的原則就是讓元件儘可能的都是無狀態的。
無狀態元件
無狀態元件只是一個render方法,沒有狀態,沒有生命週期,只是簡單的接收props渲染生成DOM結構,是一個純粹為了渲染而生的元件。相比於有狀態元件,它們簡單快捷高效,所以如果有可能的話,請儘量使用無狀態元件。
例子:
const HelloWorld = (props) => <div>{props.name}</div>; ReactDOM.render(<HelloWorld name="Hello World!" />, App);