2018-06-11 RN組件的生命周期

主題:組件的生命周期

RN組件的props和state

1.屬性(props)

它是組件的不可變屬性(組件自己不可以自己修改props)。
組件自身定義了一組props作為對外提供的接口,展示一個組件時只需要指定props作為節(jié)點的屬性。
一般組件很少需要對外公開方法(例外:工具類的靜態(tài)方法等),唯一的交互途徑就是props。所以說它也是父組件與子組件通信的橋梁。
組件自己不可以自己修改props(即:props可認為是只讀的),只可由其他組件調(diào)用它時在外部修改。

2.狀態(tài)(state)

它是組件的內(nèi)部狀態(tài)屬性,主要用來存儲組件自身需要的數(shù)據(jù)。
除了初始化時可能由props來決定,之后就完全由組件自身去維護。
組件中由系統(tǒng)定義了setState方法,每次調(diào)用setState時都會更新組件的狀態(tài),觸發(fā)render方法重新渲染界面。
需要注意的是render方法是被異步調(diào)用的,這可以保證同步的多個setState方法只會觸發(fā)一次render,這樣做是有利于提高性能的。

RN生命周期

image
可以把組件生命周期大致分為四個階段:
  • 第一階段:創(chuàng)建初始化組件的屬性類型和默認屬性;
  • 第二階段:組件類被調(diào)用(實例化)
  • 第三階段:是組件在運行和交互階段,如圖中左下角虛線框,這個階段組件可以處理用戶交互,或者接收事件更新界面;
  • 第四階段:是組件卸載消亡的階段,如圖中右下角的虛線框中,這里做一些組件的清理工作

1.創(chuàng)建階段

該階段主要發(fā)生在創(chuàng)建組件類的時候,主要作用是創(chuàng)建初始化組件的屬性類型和默認屬性。

defaultProps / getDefaultProps()

這里用來初始化默認屬性,一個控件通過this.props獲取需要的屬性。因為組件初始化后不會再次調(diào)用本方法,所以組件自己不能更改自身的props(所以一般默認props為只讀)
ES5中屬性類型和默認屬性分別通過propTypes和getDefaultProps方法實現(xiàn)
//ES5 
getDefaultProps: function() {
    return { autoPlay: false, maxLoops: 10, };
}, 
propTypes: {
    autoPlay: React.PropTypes.bool.isRequired, 
    maxLoops: React.PropTypes.number.isRequired, 
    posterFrameSrc: React.PropTypes.string.isRequired, 
    videoSrc: React.PropTypes.string.isRequired, 
},
在ES6里,可以統(tǒng)一使用static成員來實現(xiàn).
//ES6 
static defaultProps = {
    autoPlay: false, 
    maxLoops: 10, 
}; // 注意這里有分號 
static propTypes = {
    autoPlay: React.PropTypes.bool.isRequired,
    maxLoops: React.PropTypes.number.isRequired,
    posterFrameSrc: React.PropTypes.string.isRequired,
    videoSrc: React.PropTypes.string.isRequired, 
}; // 注意這里有分號

替換方法
npm install --save prop-types
import PropTypes from 'prop-types';
屬性: PropTypes.array,
屬性: PropTypes.bool,
屬性: PropTypes.func,
屬性: PropTypes.number,
屬性: PropTypes.object,
屬性: PropTypes.string,

2.實例化階段

該階段主要發(fā)生在組件類被調(diào)用(實例化)的時候。

1) constructor(props) / getInitialState()

這里是對控件的一些狀態(tài)進行初始化,由于該函數(shù)不同于getDefaultProps,在以后的過程中,會再次調(diào)用,所以可以將控制控件的狀態(tài)的一些變量放在這里初始化,如控件上顯示的文字,可以通過this.state來獲取值,通過this.setState來修改state值。
在ES5里,通過getInitialState對狀態(tài)進行初始化
//ES5
getInitialState: function() {
        return {
            loopsRemaining: this.props.maxLoops,
        };
},
在ES6里,通過constructor(構(gòu)造器)對狀態(tài)進行初始化
//ES6
constructor(props){
        super(props);
        this.state = {
            loopsRemaining: this.props.maxLoops,
        };
}

2)componentWillMount()

準(zhǔn)備加載組件。
這個調(diào)用時機是在組件創(chuàng)建,并初始化了狀態(tài)之后,在第一次繪制 render() 之前??梢栽谶@里做一些業(yè)務(wù)初始化操作,也可以設(shè)置組件狀態(tài)。這個函數(shù)在整個生命周期中只被調(diào)用一次。
如果在這個函數(shù)里面調(diào)用setState,本次的render函數(shù)可以看到更新后的state,并且只渲染一次。

3) render()

render是一個組件必須有的方法,形式為一個函數(shù),渲染界面,并返回JSX或其他組件來構(gòu)成DOM,和Android的XML布局、WPF的XAML布局類似,只能返回一個頂級元素。

4) componentDidUpdate()

調(diào)用了render方法后,組件加載成功并被成功渲染出來以后所執(zhí)行的hook函數(shù),一般會將網(wǎng)絡(luò)請求等加載數(shù)據(jù)的操作,放在這個函數(shù)里進行,來保證不會出現(xiàn)UI上的錯誤。

3. 運行(更新)階段

該階段主要發(fā)生在用戶操作之后,或者父組件有更新的時候,此時會根據(jù)用戶的操作行為,進行相應(yīng)的界面結(jié)構(gòu)調(diào)整。
觸發(fā)的流程如下:

1) componentWillReceiveProps(nextProps)

當(dāng)組件接收到新的props時,會觸發(fā)該函數(shù)。在該函數(shù)中,通??梢哉{(diào)用setState()來完成對state的修改。
輸入?yún)?shù) nextProps 是即將被設(shè)置的屬性,舊的屬性還是可以通過 this.props 來獲取。在這個回調(diào)函數(shù)里面,你可以根據(jù)屬性的變化,通過調(diào)用 this.setState() 來更新你的組件狀態(tài),這里調(diào)用更新狀態(tài)是安全的,并不會觸發(fā)額外的 render() 調(diào)用。如下:
componentWillReceiveProps: function(nextProps) {  
  this.setState({
    likesIncreasing: nextProps.likeCount > this.props.likeCount
  });
}

2) shouldComponentUpdate(nextProps, nextState)

返回布爾值(決定是否需要更新組件)
輸入?yún)?shù) nextProps 和上面的 componentWillReceiveProps 函數(shù)一樣,nextState 表示組件即將更新的狀態(tài)值。這個函數(shù)的返回值決定是否需要更新組件,如果 true 表示需要更新,繼續(xù)走后面的更新流程。否者,則不更新,直接進入等待狀態(tài)。
默認情況下,這個函數(shù)永遠返回 true 用來保證數(shù)據(jù)變化的時候 UI 能夠同步更新。在大型項目中,你可以自己重載這個函數(shù),通過檢查變化前后屬性和狀態(tài),來決定 UI 是否需要更新,能有效提高應(yīng)用性能。

3) componentWillUpdate(nextProps, nextState)

shouldComponentUpdate返回true或者調(diào)用forceUpdate之后,就會開始準(zhǔn)更新組件,并調(diào)用 componentWillUpdate()。
輸入?yún)?shù)與 shouldComponentUpdate 一樣,在這個回調(diào)中,可以做一些在更新界面之前要做的事情。需要特別注意的是,在這個函數(shù)里面,你就不能使用 this.setState 來修改狀態(tài)。這個函數(shù)調(diào)用之后,就會把 nextProps 和 nextState 分別設(shè)置到 this.props 和 this.state 中。緊接著這個函數(shù),就會調(diào)用 render() 來更新界面了。

==絕對不要在componentWillUpdate和componentDidUpdate中調(diào)用this.setState方法,否則將導(dǎo)致無限循環(huán)調(diào)用。!!!==

4) render()

再確定需要更新組件時,調(diào)用render,根據(jù)diff算法,渲染界面,生成需要更新的虛擬DOM數(shù)據(jù)。

5) componentDidUpdate()

虛擬DOM同步到DOM中后,執(zhí)行該方法,可以在這個方法中做DOM操作。
除了首次render之后調(diào)用componentDidMount,其它render結(jié)束之后都是調(diào)用componentDidUpdate。

==絕對不要在componentWillUpdate和componentDidUpdate中調(diào)用this.setState方法,否則將導(dǎo)致無限循環(huán)調(diào)用。!!!==

4. 銷毀階段

該階段主要發(fā)生組件銷亡的時候,觸發(fā)componentWillUnmount。當(dāng)組件需要從DOM中移除的時候,通常需要做一些取消事件綁定,移除虛擬DOM中對應(yīng)的組件數(shù)據(jù)結(jié)構(gòu),銷毀一些無效的定時器等工作,都可以在這個方法中處理。

componentWillUnmount()

當(dāng)組件要被從界面上移除的時候,就會調(diào)用 componentWillUnmount。
在這個函數(shù)中,可以做一些組件相關(guān)的清理工作,例如取消計時器、網(wǎng)絡(luò)請求等。

組件更新時機

更新組件(重新渲染界面)的方式有以下四種:

  • 首次渲染Initial Render,即首次加載組件
  • 調(diào)用this.setState,狀態(tài)發(fā)生改變(并不是一次setState會觸發(fā)一次render,React可能會合并操作,再一次性進行render)
  • 父組件發(fā)生更新(一般就是props發(fā)生改變,但是就算props沒有改變或者父子組件之間沒有數(shù)據(jù)交換也會觸發(fā)render)
  • 調(diào)用this.forceUpdate,強制更新
生命周期 調(diào)用次數(shù) 能否使用 setSate()
defaultProps / getDefaultProps 1(全局調(diào)用一次)
constructor / getInitialState 1
componentWillMount 1
render >=1
componentDidMount 1
componentWillReceiveProps >=0
shouldComponentUpdate >=0
componentWillUpdate >=0
componentDidUpdate >=0
componentWillUnmount 1

tips:webStorm添加RN提示插件

  1. 進入你想存儲這個文件的目錄,按住shift+鼠標(biāo)右鍵,選擇“在此處打開命令窗口”

  2. 在命令窗口中輸入 git clone https://github.com/virtoolswebplayer/ReactNative-LiveTemplate

  3. 打開webstorm, 選擇file-->Import Settings...-->在剛剛下載的文件夾里找到ReactNative.jar選擇它-->OK

  4. 提示重啟webstrom,重啟,搞定

結(jié)束

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 說在前面 關(guān)于 react 的總結(jié)過去半年就一直碎碎念著要搞起來,各(wo)種(tai)原(lan)因(le)。心...
    陳嘻嘻啊閱讀 7,030評論 7 41
  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南,這只是我在學(xué)習(xí)過程中的一些閱讀筆記,個人覺得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,944評論 1 18
  • 工作上有些不順。 放養(yǎng)的野貓明明好幾次都能乖乖等在門口這次卻又跑進屋里。 很好,今晚它沒飯吃。 夜很黑。 驀然有點...
    姜琥珀閱讀 450評論 0 1
  • 看完了第一期的國家寶藏,準(zhǔn)備來說幾句,可能會涉及到一些自己的主觀思想,但內(nèi)心熱血促使我寫下了這段觀后感。 我不是一...
    遙其左右閱讀 599評論 0 0
  • 今天翻翻網(wǎng)易云音樂無意又聽到了《free loop》這首歌,“cause it's hard for me to ...
    小二黑112233閱讀 416評論 0 0

友情鏈接更多精彩內(nèi)容