接觸React Native才一個(gè)月有余瓷炮,對(duì)這種“Learn once,Write anywhere”的移動(dòng)端開發(fā)框架越來越喜愛卸伞。不敢說自己一個(gè)多月就掌握了React Native抹镊,這里只是將自己一個(gè)多月踩過的坑和一些經(jīng)驗(yàn)心得以及教訓(xùn)分享記錄于此,并且今后也會(huì)不斷補(bǔ)充完善荤傲。
使用WebStorm開發(fā)React Native經(jīng)驗(yàn)
WebStorm個(gè)人感覺真的是最好的ReactNative 開發(fā)工具之一垮耳,特別是當(dāng)你有用過AndroidStudio的情況下,使用WebStorm絕對(duì)是最好的選擇遂黍。
通過配置直接運(yùn)行項(xiàng)目
![enter description here](http://om2bpqram.bkt.clouddn.com/1496385059159.jpg)
點(diǎn)擊WebStorm右上角的小方框中的向下箭頭终佛,選中Edit Configurations..
![enter description here](http://om2bpqram.bkt.clouddn.com/1496385172176.jpg)
在彈出來的窗口中點(diǎn)擊左上角的“+”按鈕,下拉選項(xiàng)選擇“React Native”
![enter description here](http://om2bpqram.bkt.clouddn.com/1496385351796.jpg)
右側(cè)“name”項(xiàng)隨意填寫雾家,自己能夠區(qū)分就好铃彰,默認(rèn)運(yùn)行目標(biāo)平臺(tái)為Android,因此如果要運(yùn)行的目標(biāo)平臺(tái)為iOS將Target Platform改為iOS即可芯咧。
![enter description here](http://om2bpqram.bkt.clouddn.com/1496385541594.jpg)
最后WebStorm可運(yùn)行項(xiàng)目中如下
![enter description here](http://om2bpqram.bkt.clouddn.com/1496385604021.jpg)
選中Android牙捉,點(diǎn)擊右側(cè)的綠色三角形按鈕就可在Android模擬器或真機(jī)運(yùn)行ReactNative項(xiàng)目了,iOS同理敬飒。
注意邪铲,直接運(yùn)行是在你的電腦上已經(jīng)安裝安卓模擬器或者Xcode的前提下,運(yùn)行Android端時(shí)需提前啟動(dòng)好Android模擬器,否則會(huì)提示找不到設(shè)備无拗,iOS則無需該操作带到。此外在WebStorm中運(yùn)行最常見的問題是8081端口被占用
![enter description here](http://om2bpqram.bkt.clouddn.com/1496386478708.jpg)
此時(shí)需要在終端中通過lsof命令查找占用端口的進(jìn)程PID 并通過kill 命令殺死進(jìn)程。
![enter description here](http://om2bpqram.bkt.clouddn.com/1496386543687.jpg)
最好的避免方式是在需要停止運(yùn)行英染,點(diǎn)擊停止按鈕來停止項(xiàng)目運(yùn)行
![enter description here](http://om2bpqram.bkt.clouddn.com/1496387018926.jpg)
在WebStorm中調(diào)試
在編寫的js文件中需要調(diào)試的地方打下斷點(diǎn)阴孟,然后通過WebStorm運(yùn)行項(xiàng)目,ReactNative運(yùn)行在模擬器運(yùn)行成功后中調(diào)出調(diào)試菜單税迷,點(diǎn)擊Debug JS Remotely(此處使用iOS作為示例永丝,Android基本一致)
![enter description here](http://om2bpqram.bkt.clouddn.com/1496387265719.jpg)
此時(shí)就可以根據(jù)需要進(jìn)行調(diào)試了〖快捷鍵F8是單步調(diào)試慕嚷,F(xiàn)7是步進(jìn)調(diào)試
ps.在HTML標(biāo)簽塊中打下的斷點(diǎn)是無效的
![enter description here](http://om2bpqram.bkt.clouddn.com/1496387859119.jpg)
ListView組件中的坑
如果你在ListView中renderHeader方法中加載圖片,那么在Android端會(huì)無法顯示,iOS端則不會(huì)有此問題喝检。這是React Native中的一個(gè)Bug嗅辣,還沒有徹底解決,詳見:
Render a ViewPagerAndroid in ListView.renderHeader() that the elements under ViewPagerAndroid will not display
目前暫時(shí)的解決方案如下:
<ListView
...
removeClippedSubviews={false}
/>
removeClippedSubviews 屬性挠说,表示如果子 View 超出可視區(qū)域澡谭,是否自動(dòng)移除,默認(rèn)是 true,因此設(shè)置為false顯然是犧牲了一定的性能损俭。不過目前的做法是使用FlatList替代ListView蛙奖,因?yàn)镕latList比ListView提升了很多(不過FlatList是否同樣有這個(gè)Bug還未測(cè)試)
TextInput組件中的坑
TextInput在iOS端必須設(shè)置height屬性,否則無法獲取焦點(diǎn)杆兵,Android端可不設(shè)置雁仲。
關(guān)于布局與屏幕適配的一點(diǎn)經(jīng)驗(yàn)
- 基本上所有組件都最好不指定寬高(圖片除外,必須指定寬高否則顯示圖片原大小琐脏,不好控制)攒砖,不指定寬高的組件將保持原大小,這點(diǎn)類似Android中的wrap_content.
- React Native組件大小的數(shù)值單位是dp日裙,不需要再進(jìn)行轉(zhuǎn)換
flex
style中的flex是一個(gè)很有用的屬性吹艇,有點(diǎn)類似Android中l(wèi)ayout_weight屬性
- 在根布局中指定flex:1則表示占滿全屏(view默認(rèn)寬度為100%)
- 如果一層布局中有多個(gè)組件其中只有一個(gè)組件指定了flex:1則表示該組件將占據(jù)其余組件外所剩余的空間
- 如果一層布局中有多個(gè)組件指定了flex:1,則表示這些組件所占比相同
布局方向flexDirection
ReactNative默認(rèn)布局方向?yàn)榭v向column,此時(shí)justifyContent指定縱向?qū)R方式昂拂,alignItems指定橫向?qū)R方式
橫向需指定為row受神,justifyContent指定橫向?qū)R方向,alignItems指定縱向?qū)R方式
Image的調(diào)整模式resizeMode
resizeMode屬性可調(diào)整圖片相對(duì)于容器的展現(xiàn)方式政钟,默認(rèn)為cover模式。根據(jù)實(shí)際情況靈活選擇resizeMode樟结。
cover模式只求在顯示比例不失真的情況下填充整個(gè)顯示區(qū)域养交。可以對(duì)圖片進(jìn)行放大或者縮小瓢宦,超出顯示區(qū)域的部分不顯示碎连,
也就是說,圖片可能部分會(huì)顯示不了驮履。
contain模式是要求顯示整張圖片, 可以對(duì)它進(jìn)行等比縮小,
圖片會(huì)顯示完整,可能會(huì)露出Image控件的底色鱼辙。 如果圖片寬高都小于控件寬高,則不會(huì)對(duì)圖片進(jìn)行放大玫镐。
stretch模式不考慮保持圖片原來的寬,高比.填充整個(gè)Image定義的顯示區(qū)域,這種模式顯示的圖片可能會(huì)畸形和失真倒戏。
center模式, 9月11號(hào)的0.33版本才支持,contain模式基礎(chǔ)上支持等比放大恐似。
一點(diǎn)經(jīng)驗(yàn):
- 如果要求圖片完整展示杜跷,并且圖片比較接近純色或者畫面條理不是十分清晰,可以選擇stretch。
- 如果原圖片大于展示區(qū)域葛闷,使用默認(rèn)的cover會(huì)導(dǎo)致一部分圖片區(qū)域丟失(丟失區(qū)域與設(shè)置的justifyContent和alignItems有關(guān))憋槐,如果圖片邊緣區(qū)域不重要可以使用cover模式
- 使用contain模式最好保證圖片展示區(qū)域與圖片的寬高比例相同,否則會(huì)有意想不到的適配問題淑趾。
iOS 獲取網(wǎng)絡(luò)信息API 的坑
NetInfo.isConnected.fetch().done((isConnected) => {
});
在iOS中阳仔,這個(gè)方法返回值一直是false,在Android中正常
NetInfo.fetch().done( (connectionInfo) => { } );
在iOS中扣泊,這個(gè)方法返回值一直是unknown近范,在Android中正常
因此可以通過添加網(wǎng)絡(luò)監(jiān)聽來判斷網(wǎng)絡(luò)是否可用。
當(dāng)然還有其他辦法旷赖,具體可參考:https://github.com/facebook/react-native/issues/8615
以下是其中以一個(gè)解決辦法
function handleFirstConnectivityChange(isConnected) {
if (!sConnected) {
// do action
}
NetInfo.isConnected.removeEventListener('change', handleFirstConnectivityChange);
}
if (Platform.OS === 'ios') {
NetInfo.isConnected.addEventListener('change', handleFirstConnectivityChange);
} else {
NetInfo.isConnected.fetch().then(isConnected => {
if (!sConnected) {
// do action
}
}
時(shí)間轉(zhuǎn)換
在項(xiàng)目中遇到將yyyy-MM-dd hh:mm:ss格式的時(shí)間字符串轉(zhuǎn)換成Date類型遇到了問題顺又。
let date = new Date(timeStr);
該方法在Android/iOS模擬器或真機(jī)上轉(zhuǎn)換出來的date 值為 Invalid Date(Android)/NaN(iOS),在調(diào)試模式這個(gè)值的卻完全正常的等孵。如今也讓人不得解稚照。解決辦法:
let date = new Date(Date.parse(timeStr.replace(/-/g, "/")));
使用該方法進(jìn)行時(shí)間轉(zhuǎn)換。
頁面卡頓的一個(gè)解決辦法
InteractionManager.runAfterInteractions 方法可以讓我們?cè)陧撁娴乃袆?dòng)畫執(zhí)行完后再獲取數(shù)據(jù)
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this._getListData().done()
})
}
RN加載首屏白屏明顯
使用預(yù)加載俯萌。白屏出現(xiàn)主要是因?yàn)閖sBundle加載到內(nèi)存中耗時(shí)會(huì)比較長果录。RN原本的做法是第一次打開RN頁面后才去加載jsBundle,而我們可以用空間換時(shí)間到做法咐熙,在應(yīng)用啟動(dòng)時(shí)就加載jsBundle到內(nèi)存中弱恒。