前言
學(xué)習(xí)本系列內(nèi)容需要具備一定 HTML 開發(fā)基礎(chǔ)恕酸,沒有基礎(chǔ)的朋友可以先轉(zhuǎn)至 HTML快速入門(一) 學(xué)習(xí)
本人接觸 React Native 時(shí)間并不是特別長拟杉,所以對(duì)其中的內(nèi)容和性質(zhì)了解可能會(huì)有所偏差厚脉,在學(xué)習(xí)中如果有錯(cuò)會(huì)及時(shí)修改內(nèi)容迟杂,也歡迎萬能的朋友們批評(píng)指出删铃,謝謝
文章第一版出自簡書概荷,如果出現(xiàn)圖片或頁面顯示問題螺戳,煩請(qǐng)轉(zhuǎn)至 簡書 查看 也希望喜歡的朋友可以點(diǎn)贊搁宾,謝謝
React Native 組件執(zhí)行順序介紹
- 所有的程序都有生命周期,這是開發(fā)人員關(guān)注的點(diǎn)倔幼,比如iOS中有一個(gè)
ViewDidLoad
來初始化盖腿,在React Native中又是在哪里?這邊從文檔中截取的一張圖并注釋了下损同,很好地描述了React Native組件的執(zhí)行順序
- 從圖中可以看出翩腐,在React Native中,組件的生命周期大致可以分為3個(gè)階段(
實(shí)例化階段膏燃、存在階段茂卦、銷毀階段
),其中最常接觸的為實(shí)例化階段组哩,這個(gè)階段負(fù)責(zé)組件的構(gòu)建和展示的時(shí)間等龙,需要我們根據(jù)幾個(gè)函數(shù)的調(diào)用過程,控制好組件的展示和邏輯處理
實(shí)例化階段函數(shù)功能分析
-
getDefaultProps:該函數(shù)用于初始化一些默認(rèn)屬性禁炒,通常會(huì)將固定的內(nèi)容放在這個(gè)函數(shù)中進(jìn)行初始化和賦值
- 在組件中而咆,我們可以利用
this.props
獲取在這里初始化它的屬性,由于組件初始化后幕袱,再辭使用該組件不會(huì)調(diào)用getDefaultProps
函數(shù),所以組件自己不可以修改props暴备,只可由其他組件調(diào)用它時(shí)再外部進(jìn)行修改
- 在組件中而咆,我們可以利用
-
getInitialState:該函數(shù)用于對(duì)組件一些狀態(tài)進(jìn)行初始化
- 該函數(shù)不同于getDefaultProps,在以后的過程中们豌,會(huì)再次調(diào)用涯捻,所以可以將控制控件狀態(tài)的一些變量放在這里初始化浅妆,比如控件上顯示的文字,可以通過this.state來獲取值障癌,通過
this.setState
來修改state值
var SMZQ = React.createClass({ // 用于設(shè)置一些值固定不變或上下界面值傳遞 getDefaultProps(){ return{ number1: 1, number2: 2 } }, // 用于設(shè)置一些可變或者用來刷新界面 getInitialState(){ return{ sum:0 } }, render() { return ( <View style={styles.container}> <Text>number1:{this.props.number1}</Text> <Text>number2:{this.props.number2}</Text> <Text>sum:{this.state.sum}</Text> <TouchableOpacity onPress={() => {this.setState({sum: this.props.number1 + this.props.number2})}} > <Text>計(jì)算和</Text> </TouchableOpacity> <TouchableOpacity onPress={() => {this.setState({sum: this.state.sum + 1})}} > <Text>和的基礎(chǔ)上+1</Text> </TouchableOpacity> </View> ); } });
效果:
getDefaultProps和getInitialState使用.gif- 注:一旦調(diào)用了
this.setState
方法凌外,組件一定會(huì)調(diào)用render方法,對(duì)組件進(jìn)行再次渲染涛浙,不過康辑,React框架會(huì)根據(jù)DOM的狀態(tài)自動(dòng)判斷是否需要真正渲染
- 該函數(shù)不同于getDefaultProps,在以后的過程中们豌,會(huì)再次調(diào)用涯捻,所以可以將控制控件狀態(tài)的一些變量放在這里初始化浅妆,比如控件上顯示的文字,可以通過this.state來獲取值障癌,通過
componentWillMount:相當(dāng)于OC中的
ViewWillAppear
方法,在組件簡要被加載到視圖之前調(diào)用,沒有太多的功能-
render:它是每個(gè)組件必需具備的方法轿亮,本質(zhì)上是個(gè)函數(shù)疮薇,并且返回JSX或者其他組件來構(gòu)成DOM,和Android的XML布局類似
- 在該函數(shù)中我注,只能通過this.state和this.props來訪問之前在函數(shù)中初始化的數(shù)值
- 注:只能返回一個(gè)頂級(jí)元素
-
componentDidMount:在調(diào)用了render方法按咒,組件加載成功并被成功渲染出來之后,所要執(zhí)行的后續(xù)操作但骨,一般都會(huì)在這個(gè)函數(shù)中進(jìn)行励七,比如經(jīng)常要面對(duì)的網(wǎng)絡(luò)請(qǐng)求等加載數(shù)據(jù)操作
- 因?yàn)閁I已經(jīng)成功渲染,而且這里面是異步的奔缠,索引放在這個(gè)函數(shù)進(jìn)行數(shù)據(jù)的請(qǐng)求等復(fù)雜的操作掠抬,不會(huì)出現(xiàn)UI錯(cuò)誤
存在階段函數(shù)功能分析
- componentWillReceiveProps:指父元素對(duì)組件的props或state進(jìn)行了修改
- shouldComponentUpadate:一般用于優(yōu)化,可以返回false或true來控制是否進(jìn)行渲染
- componentWillUpdate:組件刷新前調(diào)用添坊,類似componentWillMount
- componentDidUpdate:更新后的hook
銷毀階段函數(shù)功能分析
- 用于清理一些無用的內(nèi)容剿另,如:點(diǎn)擊事件Listener,只有一個(gè)過程:componentWillUnmount
常用知識(shí)點(diǎn)分析
-
this.state:開發(fā)中,組件肯定要與用戶互動(dòng)贬蛙,React的一大創(chuàng)新就是將組件看成一個(gè)狀態(tài)機(jī)雨女,一開始有一個(gè)初始狀態(tài),然后用戶互動(dòng)阳准,導(dǎo)致狀態(tài)變化氛堕,從而觸發(fā)重新渲染UI,舉個(gè)例子
var SMZQ = React.createClass({ // 用于設(shè)置一些可變或者用來刷新界面 getInitialState(){ return{ isPositive: true, content:'5是不是負(fù)數(shù)' } }, render() { return ( <View style={styles.container}> <TouchableOpacity onPress={() => {this.dealWithState(this.state.isPositive, 5)}} > <Text>{this.state.content}</Text> </TouchableOpacity> </View> ); }, dealWithState: function (data:Boolean, num:int) { var isPositive, content; if (num > 0){ isPositive = false; content = '值不是負(fù)數(shù)'; }else { isPositive = true; content = '值是負(fù)數(shù)'; } this.setState({ isPositive: isPositive, content: content }); } });
效果:
this.state探究.gif- 當(dāng)用戶點(diǎn)擊組件野蝇,導(dǎo)致狀態(tài)變化讼稚,this.setState方法就修改狀態(tài)值,每次修改以后绕沈,會(huì)自動(dòng)調(diào)用this.render方法锐想,再次渲染組件
- 可以把組件看成一個(gè)狀態(tài)機(jī),根據(jù)不同的status有不同的UI展示乍狐,只要使用setState改變狀態(tài)值赠摇,根據(jù)diff算法算出有差值后,就會(huì)執(zhí)行ReactDom的render方法,重新渲染頁面
- 注:由于this.props和this.state都用于描述組件的特性藕帜,可能會(huì)產(chǎn)生混淆烫罩,一個(gè)簡單的區(qū)分方法就是 —— this.props表示那些一旦定義,就不再更改的特性洽故,而this.state是會(huì)隨著用戶互動(dòng)而產(chǎn)生改變的特性
-
獲取真實(shí)的DOM節(jié)點(diǎn)
- 在React Native中贝攒,組件并不是真實(shí)的DOM節(jié)點(diǎn),而是存在于內(nèi)存中的一種數(shù)據(jù)結(jié)構(gòu) 时甚,叫虛擬DOM
- 只有當(dāng)它插入文檔后隘弊,才會(huì)變成真實(shí)的DOM
- 根據(jù)React的設(shè)計(jì),所有DOM變動(dòng)撞秋,都先在虛擬DOM上發(fā)生长捧,然后再將實(shí)際發(fā)生變動(dòng)的部分,反應(yīng)在真實(shí)DOM上吻贿,這種算法叫做DOM diff,它可以極大提高網(wǎng)頁的性能表現(xiàn)
- 有時(shí)需要從組件獲取真實(shí)DOM節(jié)點(diǎn),這時(shí)就需要用到ref屬性哑子,可以看下面的示例加深理解
var SMZQ = React.createClass({ render() { return ( <View ref="mainView" style={styles.container}> <TouchableOpacity onPress={() => {this.dealWithState()}} > <Text>值</Text> </TouchableOpacity> <TextInput ref="mytextInput"></TextInput> </View> ); }, dealWithState: function () { // 讓輸入框獲得焦點(diǎn) this.refs.mytextInput.focus(); // 查看內(nèi)容屬性 console.log(this.refs.mainView); } });
效果:
打印結(jié)果.png- 可以看出舅列,組件View的子節(jié)點(diǎn)有一個(gè)文本輸入框,用于獲取用戶的輸入卧蜓,這時(shí)就必須獲取真實(shí)的DOM節(jié)點(diǎn)帐要,虛擬DOM是拿不到用戶輸入的,為了做到這一點(diǎn)弥奸,文本輸入框必須有一個(gè)ref屬性榨惠,然后this.refs.refName就會(huì)返回這個(gè)真實(shí)的DOM節(jié)點(diǎn)
- 需要注意的是,由于this.refs.refName屬性獲取的是真實(shí)DOM盛霎,所有必須等到虛擬DOM插入文檔后赠橙,才能使用這個(gè)屬性,否則會(huì)報(bào)錯(cuò)愤炸。上面代碼中期揪,通過組件指定Click事件的回調(diào)函數(shù),確保只有等到真實(shí)DOM發(fā)生Click事件之后规个,才會(huì)讀取this.refs.refName屬性
補(bǔ)充
- 什么是DOM Diff算法(下面內(nèi)容是搜索的內(nèi)容)
- Web界面由DOM樹來構(gòu)成凤薛,當(dāng)其中某一部分發(fā)生變化時(shí),其實(shí)就是對(duì)應(yīng)的某個(gè)DOM節(jié)點(diǎn)發(fā)生了變化诞仓。在React中缤苫,構(gòu)建UI界面的思路是由當(dāng)前狀態(tài)決定界面。前后兩個(gè)狀態(tài)就對(duì)應(yīng)兩套界面墅拭,然后由React來比較兩個(gè)界面的區(qū)別活玲,這就需要對(duì)DOM樹進(jìn)行Diff算法分析
- 即給定任意兩棵樹,找到最少的轉(zhuǎn)換步驟。但是標(biāo)準(zhǔn)的的Diff算法復(fù)雜度需要O(n^3)翼虫,這顯然無法滿足性能要求屑柔。要達(dá)到每次界面都可以整體刷新界面的目的,勢必需要對(duì)算法進(jìn)行優(yōu)化珍剑。這看上去非常有難度掸宛,然而Facebook工程師卻做到了,他們結(jié)合Web界面的特點(diǎn)做出了兩個(gè)簡單的假設(shè)招拙,使得Diff算法復(fù)雜度直接降低到O(n)
- 兩個(gè)相同組件產(chǎn)生類似的DOM結(jié)構(gòu)唧瘾,不同的組件產(chǎn)生不同的DOM結(jié)構(gòu)
- 對(duì)于同一層次的一組子節(jié)點(diǎn),它們可以通過唯一的id進(jìn)行區(qū)分
-算法上的優(yōu)化是React整個(gè)界面Render的基礎(chǔ)别凤,事實(shí)也證明這兩個(gè)假設(shè)是合理而精確的饰序,保證了整體界面構(gòu)建的性能