.關(guān)于style
style用于標(biāo)注組件的布局屬性酱酬,一般情況下有兩種寫法形式:
內(nèi)連形式一:
抽象形式二:
conststyles=StyleSheet.create({container:{flex:1,justifyContent:'center',alignItems:'center',backgroundColor:'#F5FCFF',})<View style={styles.container}/>
兩種形式都可以用于添加組件布局屬性妹沙,但一般情況下酪呻,在組件所屬目錄下猴凹,創(chuàng)建名為styles.js的文件夾揽思,使用第二種形式在文件內(nèi)統(tǒng)一創(chuàng)建style,并對外export肩狂。
這樣做的好處一方面是使代碼清晰整潔摘完,不冗余,方便復(fù)用和修改傻谁,另一方面是防止每次組件render時孝治,頻繁的進(jìn)行style創(chuàng)建。
還有一種情況是內(nèi)連和抽象形式連用形成包裹形式:
<View style={[styles.container,this.props.style]}/>
這種形式在進(jìn)行自定義組件的時候十分常見,為style賦值一個數(shù)組谈飒,第一個數(shù)組對象一般設(shè)置為組件的固有布局屬性或默認(rèn)布局屬性岂座,第二個數(shù)組對象為組件使用時,外部對組件布局屬性的自定義步绸。如果兩個布局屬性存在同樣的關(guān)鍵字時掺逼,以第二的布局屬性為準(zhǔn)吃媒。
2.關(guān)于ref
組件的ref字段一般被用來獲取組件的對象瓤介,一般書寫形式如下:
compoentDidMount(){this.refs.view// 獲取到view組件對象this._scroll.scrollTo({y:10,x:10})//獲取到ScrollView對象,并執(zhí)行scrollTo()}....<View ref='view'></View><TextInput ref={(input)=>{//此處可以對TextInput組件進(jìn)行操作赘那,比如focus()}}/><ScrollView ref={(scroll)=>this._scroll=scroll}/>
可以嘗試打印一下通過ref獲取到的組件對象刑桑,例如打印scrollview的組件對象,可以找到組件對象可以調(diào)用的方法募舟、組件的屬性和其子組件與父組件信息祠斧。
ref僅可以在組件被render到界面后,才可以調(diào)用拱礁,否則會返回undefined琢锋;
3.關(guān)于image
關(guān)于Image組件,目前版本呢灶,在iOS和Android平臺上行為略微不一致吴超,當(dāng)不給Image設(shè)置source或source不可用時,僅設(shè)置布局屬性時鸯乃,iOS端會顯示根據(jù)布局屬性生成無圖組件鲸阻,進(jìn)行占位;Android端則不會生成無圖組件進(jìn)行占位,即便設(shè)置了明確的長高屬性缨睡。
4.關(guān)于onLayout和NativeMethodsMixin
每個組件都可以設(shè)置onLayout屬性來獲取組件的位置信息
<View onLayout={(e)=>{e.nativeEvent即是組件的位置信息}/>
但通過onLayout獲取到的位置信息只是相對于父組件的位置坐標(biāo)鸟悴,而不是相對于屏幕位置的絕對坐標(biāo)。
通過對NativeMethodsMixin方法的調(diào)用奖年,可以幫助我們直接對組件進(jìn)行操作细诸,其中一方面功能就是獲取組件在最底層視圖上顯示的尺寸。
this.refs.view.measure((x,y,width,height,pageX,pageY)=>{console.log(x,y,width,pageX,pageY,height);})
但是陋守,這個方法需要預(yù)留反應(yīng)時間揍堰,目前版本中,在componentDidMount中不可以調(diào)用此方法嗅义,雖然不會報錯屏歹,但返回結(jié)果全部為0;正如官方文檔所說之碗,如果想更快的獲取組件尺寸蝙眶,請使用onLayout;
NativeMethodsMixin還有兩個比較常用的方法:measureInWindow和measureLayout。當(dāng)設(shè)計(jì)模式為在原生應(yīng)用中嵌入React Native窗口時幽纷,可以使用measureInWindow獲得組件相對于屏幕的坐標(biāo)信息式塌,參數(shù)是一個callBack,用法參照measure友浸;measureLayout可以用來獲取組件和目標(biāo)組件之間的相對坐標(biāo)峰尝。參數(shù)有三個:第一個為目標(biāo)視圖的節(jié)點(diǎn),第二個參數(shù)為成功時的回調(diào)收恢,第三個參數(shù)為失敗時的回調(diào)武学。獲取組件節(jié)點(diǎn)使用findNodeHandle,從0.27版本后伦意,該方法引用方式變?yōu)?/p>
import{findNodeHandle}from'react-native';
對于onLayout還有一點(diǎn)疑問火窒,如果調(diào)用如下代碼
log}>? ? log}>? ? ? ? log}></View></View></View>
即對一個多層級的組件都設(shè)置onLayout屬性時,Android端外層onLayout的觸發(fā)會比內(nèi)層快一點(diǎn)驮肉,而iOS端onLayout的觸發(fā)則是不固定的熏矿,同時觸發(fā)時快時慢。雖然相差時間都是毫秒級別离钝,目前沒有發(fā)現(xiàn)影響票编,但不排除特定狀態(tài)下會產(chǎn)生bug。
5.關(guān)于Immuatble.js
Immutable.js 是facebook的一個js庫卵渴,目的就是為JavaScript添加不可變的數(shù)據(jù)類型慧域。React Native中在使用state控制視圖時,可以通過使用Immutable.js來進(jìn)行state判斷奖恰,確定是否刷新視圖吊趾。
Immutable的語法不過多介紹,此處只介紹Immutable的is方法瑟啃。
is方法用來比較兩個Immutable類型的數(shù)據(jù)是否相等论泛,此處的比較為值比較。與之對應(yīng)的Object.is和 === 則是進(jìn)行地址比較蛹屿。
lettest1=Immutable.fromJS({a:{b:1}});lettest2=Immutable.fromJS({a:{b:2}});lettemp=test2.setIn(['a','b'],1);//將鍵b的值改為1console.log(Immutable.is(test1,temp));//打印結(jié)果為truelettest3={a:1,b:2};lettest4={a:1,b:2};console.log(Object.is(test3,test4));//打印結(jié)果為falseconsole.log(test3===test4);//打印結(jié)果為false
通過使用Immutable.js,可以在shouldComponentUpdate中屁奏,完成對states和props的判斷。其他用法詳見文檔和鏈接
6.關(guān)于視圖渲染刷新
6.1 過度渲染
React Native組件的渲染都在render函數(shù)中執(zhí)行并return错负,即每觸發(fā)一次render函數(shù)都要重新渲染一次組件坟瓢。而每次對state的修改則會觸發(fā)一次render,將整個組件重新渲染犹撒。這就將導(dǎo)致一個問題折联,即過度渲染。有時候我們頻繁的進(jìn)行state操作時识颊,頻繁的觸發(fā)render诚镰,導(dǎo)致頁面卡頓,性能下降,動畫掉幀等一系列問題清笨。
6.2 setNativeProps
setNativeProps其實(shí)是對組件底層進(jìn)行操作月杉,而不是在RN框架層面進(jìn)行組件的設(shè)置,所以調(diào)用setNativeProps方法可以規(guī)避render等組件相關(guān)方法的觸發(fā)抠艾,但是官方建議苛萎,能用state和shouldcomponentUpdate解決時就不用setNativeProps,因?yàn)槭褂胹etNativeProps可能會導(dǎo)致代碼結(jié)構(gòu)不是很清晰或state混亂检号。所以setNaiveprops一般被用于進(jìn)行動畫設(shè)置和增強(qiáng)視覺效果方面腌歉。用法如下:
this.refs.view.setNativeProps({backgroundColor:'red'})//將view背景改為紅色
6.3 shouldComponentUpdate
在shouldComponentUpdate方法中我們可以判斷組件下一組props和state的變化來決定是否觸發(fā)render,重新渲染組件谨敛。此處可以使用上面所提到的Immuatble.js庫究履。
具體寫法
shouldComponentUpdate(nextProps,nextState){constthisProps=this.props||{},thisState=this.state||{};if(Object.keys(thisProps).length!==Object.keys(nextProps).length||Object.keys(thisState).length!==Object.keys(nextState).length){returntrue;}for(constkeyinnextProps){if((thisProps[key]!==nextProps[key]||!is(Immutable.fromJS(thisProps[key]),Immutable.fromJS(nextProps[key])))&&typeof(thisProps[key])!="function"){returntrue;}}for(constkeyinnextState){if(thisState[key]!==nextState[key]||!is(thisState[key],nextState[key])){returntrue;}}returnfalse;}
基本的shouldComponentUpdate的寫法如上所示滤否,根據(jù)組件需求進(jìn)行微調(diào)即可脸狸。但需要注意的是,當(dāng)state或者props中存在function時藐俺,此時比較state和props炊甲,總會返回false,即previousState(props)和nextState(props)始終不相等欲芹,所以一般情況下比較兩者時卿啡,屏蔽function類型。
6.4 組件化
組件化的好處一方面是為了進(jìn)行組件的復(fù)用菱父,還有一方面是進(jìn)行組件是否重新渲染的判斷颈娜。例如一個組件有7個層級,當(dāng)組件重新渲染時浙宜,就要把7個層級都渲染一遍官辽,而且因?yàn)?個層級組件都寫在了一個render里,不僅代碼臃腫粟瞬,而且無法進(jìn)行區(qū)別判斷是否渲染同仆。所以盡量將代碼抽離,實(shí)現(xiàn)組件化裙品。
7.關(guān)于Promise俗批、async和await
Promise對象是ES6新增的,常作為異步結(jié)果的返回值市怎,例如:本地數(shù)據(jù)存儲或fetch網(wǎng)絡(luò)請求岁忘。async函數(shù)同樣是ES6新增的,需要同await聯(lián)合使用区匠。所以一般情況下同時使用兩者去進(jìn)行異步處理干像,以網(wǎng)絡(luò)請求為例
asyncsomeHandle(url){try{letresult=awaitfetch(url);console.log(result)returnresult;}catch(err){console.log(err);}}
但是aysnc函數(shù)有一個特點(diǎn)是假如fetch等異步操作返回reject,那么async函數(shù)將直接返回reject狀態(tài),而不會往下繼續(xù)執(zhí)行蝠筑。即假如fetch若返回reject狞膘,將不會執(zhí)行下面的打印。
可以在async函數(shù)內(nèi)加上try...catch什乙,來收集異步操作的錯誤信息挽封。
8.關(guān)于Redux
Redux是一個state管理框架,只存在一個store來存儲所有的state臣镣,只可以通過觸發(fā)action辅愿,action觸發(fā)reducer,去修改store里的state忆某,來確保state的狀態(tài)改變行為可控点待。
8.0 必備框架
react-redux 、redux 弃舒、redux-thunk即可癞埠,全部可以通過
npm install --save 框架名
安裝
8.1 action
action相當(dāng)于一個觸發(fā)動作,告訴reducer去修改state聋呢。
一般的action形式:
someHandle(value){return{type:someType,value,}}
action函數(shù)必須返回一個包含type的對象苗踪,其他字段和對象結(jié)構(gòu)可以自行設(shè)計(jì),返回type的目的是為了在reducer進(jìn)行響應(yīng)的時候進(jìn)行判斷削锰,具體如何哪個state通铲。
8.2 reducer
reducer函數(shù)是通過action觸發(fā)的,state的修改是在該函數(shù)內(nèi)進(jìn)行的器贩。
一般的reducer形式:
constinitialState=Map({number:1,opacity:0,offset:0})exportdefaultfunctionsomeHandle(state=initialState,action={}){switch(action.type){caseSOMETYPE:return//此處返回操作過的statedefault:returnstate;}}
注意reducer中颅夺,不可以直接修改state,需要根據(jù)操作蛹稍,生成新state吧黄,并返回,reducer需要保證數(shù)據(jù)的唯一和不可變稳摄,所以此處的state可以使用Immutable.js進(jìn)行數(shù)據(jù)類型的定義稚字。
8.3 redux-thunk
redux-thunk是一個redux的中間件,可以使某一action可以出發(fā)另一個action,目的是為了可以在action函數(shù)中進(jìn)行異步操作厦酬,例如進(jìn)行網(wǎng)絡(luò)請求獲取json數(shù)據(jù)并處理胆描。
someHandle(){return(dispatch,getState){//一些異步處理dispatch({type:someType,...})//觸發(fā)reducer}}
該框架不是實(shí)現(xiàn)redux的必須框架,中間件可以自行定義仗阅。
8.4 其他
使用redux結(jié)構(gòu)管理state不一定總是有益的昌讲,在項(xiàng)目需求簡單時,接入該結(jié)構(gòu)完全沒有必要减噪。而且在自定義組件是也不需要引入該結(jié)構(gòu)短绸,具體情況還需要按照項(xiàng)目需求進(jìn)行處理车吹。
redux在React Native中的工作其實(shí)是控制每個組件的props,通過改變組件的props醋闭,達(dá)到組件渲染和狀態(tài)的可控窄驹,所以redux的state并不代表RN框架的state,也不是對state的取代证逻,而是另一種形式的狀態(tài)機(jī)乐埠。兩者各有利弊,結(jié)合使用效果更佳囚企。