react-navigation是React Native中很是著名的一個頁面導航庫,能夠實現各類頁面跳轉,它是React Native社區總結出來的精華。有了這個庫,咱們能夠實現相似iOS中UINavigationController的導航效果、常見的tabBar頁面和Android中側滑Drawer的效果,很是方便好用。html
本篇文章主要介紹react-navigation的基本功能,以及一個我在實際運用中遇到的問題和解決方案,將這個方案分享一下,也許有人會遇到一樣的問題可能用得上。react
這裏說的三大組件實際上是react-navigation的三個基本的navigation組件git
StackNavigator——包含導航欄的頁面導航組件,能夠實現相似iOS端UINavigationController的導航效果。在iOS中頁面跳轉效果就是push和pop的方式,Android中就是modal的方式從底部彈起一個頁面返回時dismiss。github
TabNavigator——底部展現tabBar的頁面導航組件,這個頁面效果在app中是最多見的了。react-native
DrawerNavigator——實現側邊欄抽屜頁面的導航組件,這種頁面設計效果也是很是經常使用的。瀏覽器
在以前的文章中也簡單用到了TabNavigator和StackNavigator實現電影demo。經過以上三種Navigator組件的組合使用,咱們能夠實現絕大多數狀況下的頁面導航,應付平常開發的各類場景基本上沒問題。bash
三大基本Navigator組件的使用能夠查閱官方文檔,有簡單的demo示例,這裏很少贅述。除此以外,官方文檔還更新了很多東西,這比起以前我剛使用它的時候豐富了太多,隨着react-navigation的迭代升級,這個庫會愈來愈完善,下面來看看官方文檔中有哪些乾貨。react-router
iPhone X與以前的iPhone都不同,屏幕頂部多了個劉海,底部home鍵被橫條(Home Indicator)取代,分辨率提高,導航欄和狀態欄高度都改變了。在適配時須要使頂部標題不被劉海遮蓋,底部內容不被橫條覆蓋。這一點react-navigation也考慮到了,新增了SafeAreaView組件來解決UI適配問題。這一點官方文檔有詳細示例reactnavigation.org/docs/handli…。app
在使用SafeAreaView時須要注意,並非說你把全部的UI組件都放到SafeAreaView裏面,而後render函數返回一個SafeAreaView組件就沒問題了。這要看狀況而定,能夠參考react-navigation官方demo。框架
在iOS中狀態欄有兩種樣式,default和light-content,在頁面切換時不一樣的頁面要顯示不一樣顏色,狀態欄顏色顯示對應的樣式會使UI看起來更加協調美觀。這裏就講到了怎樣配置狀態欄樣式Different status bar configuration based on route。
在Android中常用點擊實體返回鍵的方式返回到上個頁面,能夠經過監聽的方式捕獲用戶點擊返回鍵的事件,根據實際狀況來決定是否要當即返回上一個頁面。
假設一個頁面A中嵌入了頁面B和C,頁面A和頁面D是由StackNavigator控制的。若是想要點擊頁面B中的一個button跳轉到頁面D,頁面B須要獲取到A中的navigation才能跳轉。由於B是一個子組件,它並不直接由StackNavigator控制,得不到這個navigation屬性就沒法作跳轉。react-navigation中使用withNavigation解決了這個問題。
import React from 'react';
import { Button } from 'react-native';
import { withNavigation } from 'react-navigation';
class MyBackButton extends React.Component {
render() {
return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />;
}
}
// withNavigation returns a component that wraps MyBackButton and passes in the
// navigation prop
export default withNavigation(MyBackButton);
複製代碼
假設有這樣一個場景,在瀏覽器中點擊了一個連接要跳轉到你本身的app中某個特定的頁面,該怎麼處理呢?react-navigation官方文檔以StackNavigator爲例講解了如何處理外部uri來進行指定頁面的跳轉。
官方文檔以Google Analytics爲例講解了怎樣使用第三方SDK進行頁面跟蹤和統計。這裏推薦友盟統計,官方對react native中使用統計有文檔說明。友盟統計ReactNative文檔。
官方文檔詳細講解了怎樣集成Redux並使用它來管理頁面導航,github上還給出了完整的demo。能夠仔細看看文檔一步步集成Redux。
除了上面提到的三大Navigator組件,集成Redux管理頁面導航以外,還可使用react-navigation中的StackRouter、TabRouter自定義Router來管理頁面導航。這部份內容是react-navigation的高級用法,能夠參考官方demo,本身動手實現一個自定義頁面導航。這裏我實現了一個左側顯示tabBar控制右側頁面切換顯示的導航,用於pad端,Demo地址在這裏。pad端運行效果以下:
在使用react-navigation的過程當中,我遇到一個問題。App中多個界面都須要調用接口獲取數據,接口必傳token參數,而token又是登陸後才獲取的。假如同一個帳號在其它設備登陸,那麼當前設備調用接口時必然會出現token失效致使請求失敗的狀況,這就是單點登陸形成的問題。若是一個頁面有兩個以上接口須要調用,而每一個接口都會報錯,在每一個地方都進行錯誤處理顯然是不明智的。
例如,接口請求失敗,咱們須要從新登陸,若是每一個頁面,每一個出錯的地方都寫跳轉代碼,那整個項目代碼就太冗餘了。因此對接口的業務邏輯進行處理作統一跳轉是更爲合理的選擇。可是接口代碼咱們通常會封裝起來,不會寫在UI代碼裏,怎樣才能獲取到當前正在顯示的那個界面和navigation呢?
這個問題我當時思考了不少方案,因爲對react-navigation的理解和使用尚未特別純熟,因此一時之間沒有好的解決方案,直到在stackoverflow上發現了這個問答,給出了一個有意思的解決方法,地址:stackoverflow.com/questions/4…。
經過建立BaseComponent,在初始化時獲取頁面的實例,讓處於路由中的每一個UI頁面都繼承於這個BaseComponent,就能在任何其它地方獲取到當前正在顯示的頁面,從而調用這個頁面的navigation進行跳轉。這裏並無用到其它框架(如Redux)就解決了這個問題。在實際項目中進行驗證後確認這個方案是可行的。我另外寫了個簡單的demo,以供參考,demo地址:github.com/mrarronz/re…。
react-navigation真的是很是好用的一個導航庫,官方文檔更新後更加完善,給出了許多示例,學習起來更加容易上手,同時還推薦了其它庫如react-native-router-flux、react-native-navigation、react-router-native,這些也都是很是好的開源庫。
關於頁面外獲取navigation的方法,相信隨着不斷的深刻學習,必定會有更多的解決方式,解決方案少是由於咱們知道的還不夠多。
PS: 順便推薦一個工具Expo,它是一個圍繞ReactNative打造的工具鏈,用來幫助咱們使用JS和React建立原生的iOS和Android應用。react-navigation中的部分demo集成到Expo,Expo有安卓和iOS的客戶端app,下載安裝後,能夠在Expo中經過掃二維碼的方式打開demo直接看到運行效果,很是好用。Github上不少開源的app都集成了Expo,能夠直接掃碼查看效果,趕忙安裝吧~