前段時間開始學習React Native,然後試著開始做一個小專案,在練手的同時,分享出來希望和各位同學互相學習react-native專案。之前寫過專案相關的文章,沒看過的同學可以參考一下:
- React-native專案入門與思考
- Flux, Reflux,Redux 學習與思考
- React native 專案入門(知乎日報,豆瓣電影,[one]一個)
- React native 專案進階(redux, redux saga, redux logger)
React Native專案效果
目前專案完成了(One 【一個】)主體介面功能,當然功能和原App還有較大的差距,之前主要對ios進行了適配,這兩天對Android也進行了一些調整。有什麼bug大家可以評論或者在github上提issue。先看一下效果圖:
這裡貼的是ios的效果圖,android端的類似。接下來介紹專案的結構,用到的一些第三方庫,以及專案過程中的小坑。
專案結構
- Pages
專案的主要介面,目錄下有One、Douban、Zhihu三個資料夾,分別對應one、豆瓣、知乎日報三個應用,其中one是完成度相對比較高的,其他兩個應用介面很少。 - Assets
目錄下存放了專案中用到了一些圖示,這裡存放的是android和ios的共有圖示,比如one主介面下面的四個圖示。android和ios的launch icon是在各自工程中分別設定的。 - Constants
定義專案中的常量 - Components
專案的一些自定義components,可以在多個pages中使用。 - Styles
定義常用的介面style,使用時可以直接引用,模擬android的styles,這樣就不需要在每個page中重複定義styles - Utils
定義常用的一些工具類,如網路請求、時間格式、展示屬性等。 - Actions
- reducers
- sagas
這三個目錄是redux相關的一些方法,相關的介紹可以檢視 React native 專案進階(redux, redux saga, redux logger),當然閱讀之前最好有redux基礎,推薦redux的學習教程:
leonshi.com/redux-saga-…
cn.redux.js.org/index.html
第三方庫
React Native 從第一次提交到現在已經有20個月的時間,目前github上有近4萬star,很多大牛貢獻了各種第三方庫,目前開始學習React Native對於新人初學者來說文件和社群非常友好。這裡羅列下用到的第三方庫:
"react-native-button": "github:ide/react-native-button",
"react-native-datepicker": "^1.3.2",
"react-native-drawer": "^2.2.2",
"react-native-fs": "^2.0.1-rc.2",
"react-native-root-toast": "^1.0.3",
"react-native-router-flux": "[3.30.1]",
"react-native-scrollable-tab-view": "0.6.0",
"react-native-sound": "^0.8.3",
"react-native-viewpager": "^0.2.1",
"react-redux": "^4.4.5",
"redux": "^3.6.0",
"redux-logger": "^2.6.1",
"redux-saga": "^0.11.1"複製程式碼
其中部分比較簡單,有些在之前的文章中進行了介紹,下面主要介紹:
"react-native-viewpager": "^0.2.1",
"react-native-scrollable-tab-view": "0.6.0",
"react-native-sound": "^0.8.3",
"react-native-fs": "^2.0.1-rc.2",複製程式碼
React-Native-ViewPager
是一個viewpager,one專案中的首頁、文章頁、音樂頁均使用了viewpager,使用率很高,先看一個demo:
<ViewPager
dataSource={this.state.banners}
renderPage={this.renderBanners}
isLoop={true}
autoPlay={true}
/>複製程式碼
dataSource定義資料來源,其資料來源的定義過程是:
var bannerDataSource = new ViewPager.DataSource({
pageHasChanged: (p1, p2) => p1 !== p2,
});
banners: bannerDataSource.cloneWithPages([]),複製程式碼
renderPage用於展示每個pager的介面
renderBanners(data, pageID) {
return (
<Image style={{
height: 140,
width: deviceWidth,
}} source={{uri: data.cover}}>
</Image>
);
}複製程式碼
isLoop 是否輪播
autoPlay 是否自動播放
renderPageIndicator定義indicator的樣式 ,當然可以使用default的樣式,這裡是一個示例,隱藏掉indicator:
renderPageIndicator={()=>(<View style={{width: 0, height: 0}}></View>)}複製程式碼
react-native-scrollable-tab-view
react-native-scrollable-tab-view用於定義應用的主tab,專案中主要定義了one的四個tab,可以滑螢幕切換介面,在專案中由於各個子介面自身有左右切換的需求,因此關閉了該功能。
部分設定:
renderTabBar
自定義tabbar,如專案中自定義了四個tab的樣式onChangeTab
當tab切換時回撥locked
是否鎖定,鎖定時不能左右滑動page
設定選中的tab
專案使用示例:
<ScrollableTabView initialPage={0} locked={true} prerenderingSiblingsNumber={1} tabBarPosition="bottom"
renderTabBar={()=><FacebookTabBar tabIcons={this.tabIcons}/>}>
<OneHome tabLabel="首頁"/>
<OneRead tabLabel="閱讀"/>
<OneMusic tabLabel="音樂"/>
<OneFilm tabLabel="電影"/>
</ScrollableTabView>複製程式碼
react-native-fs
react-native-sound
這兩個主要用於one音樂的播放,其中react-native-fs主要用於音樂的下載,react-native-sound用於本地檔案的播放,這兩個庫都用到了原生方法,因此需要分別在android和ios專案中進行設定使用:
ios端
1.
如圖需要Add兩個lib的*.xcodeproj到主工程的Libraries中,然後
2.
如圖Add所有的*.a檔案,編譯執行就ok了。
Android 端
- 在setting.gradle中新增:
include ':app' include ':react-native-fs' project(':react-native-fs').projectDir = new File(settingsDir, '../node_modules/react-native-fs/android') include ':RNSound', ':app' project(':RNSound').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sound/android')複製程式碼
- 在build.gradle中新增:
compile project(':react-native-fs') compile project(':RNSound')複製程式碼
注意新增位置要正確,對程式碼進行重新編譯,在Android目錄機構下即可以看到RNSound、react-native-fs兩個module。
兩個lib在react-native 中的使用比較簡單,可以參考one專案中的使用:react-native-sound 和react-native-fs的使用
專案中踩坑
- Image中設定source={{url:"http://..."}}
在ios中這樣設定是沒有問題的,但是android中不起效, 需要設定source={{uri:"http://..."}},另關於Image,目前必須設定width和height,官方解釋為防止在進行渲染時如果寬高不固定容易造成介面跳動,影響使用者體驗。 - react-native-sound 播放路徑問題
其中'whoosh.mp3'為相對路徑,Sound.MAIN_BUNDLE為基本路徑,在ios中可用,但是在android中提示找不到路徑,最終第一個引數設定絕對路徑,第二個引數設定為 '' 空串。var whoosh = new Sound('whoosh.mp3', Sound.MAIN_BUNDLE, (error) => { if (error) { console.log('failed to load the sound', error); } else { // loaded successfully console.log('duration in seconds: ' + whoosh.getDuration() + 'number of channels: ' + whoosh.getNumberOfChannels()); } });複製程式碼
- react-native-sound 播放問題
需要在sound建立成功的回撥中啟動播放,不可以直接寫在建立的語句之後。musicHandler = new Sound(`${RNFS.DocumentDirectoryPath}/music.mp3`, '',(error) => { if (error) { console.log('failed to load the sound', error); } else { // loaded successfully this.playSound(); } });複製程式碼
4.gif圖問題
ios的Image支援直接播放gif圖,android需要新增lib,在build.gradle的dependencies中新增:
compile 'com.facebook.fresco:animated-gif:0.12.0'//for gif複製程式碼
5.佈局問題
這種佈局可以設定marginTop為負值即可。
- 關於react-native-viewpager和react-native-srollable-tab-view巢狀問題
當發生巢狀時,可能發生介面的錯位,這是可以設定view的style:overflow: 'hidden',可以避免介面疊加錯位。
總結
目前專案中還有較多的問題,尤其是Android端,之後還會繼續進行完善。根據目前的開發體驗,感覺react native非常適合於展示型別的app,開發效率非常高,但是在Android上體驗要低於ios,有很大的優化空間。
接下來在繼續完善專案的基礎上,繼續學習相關的知識,爭取做出自己的東西,實現在React-native專案入門與思考中立下的flag。
歡迎關注公眾號wutongke,每天推送移動開發前沿技術文章:
推薦閱讀:
React-native專案入門與思考
React native 專案入門(知乎日報,豆瓣電影,[one]一個)
React native 專案進階(redux, redux saga, redux logger)
React Native 專案2(One 【一個】客戶端)