React Native 之 react-navigation(堆疊導航器) 的使用
做應用肯定不可能就一個介面,所以這裡涉及到我們介面跳轉的問題,那RN是怎麼利用導航器來實現跳轉的呢?我們結合官網給出的例子進行分析,後面筆者發現其實RN的某些思路其實跟Android大同小異,如果你對Android的啟動模式有了解還有Android的棧的理解,我相信理解這個應該不會很複雜 D)
首先如果想用react-navigation就要先安裝它,react-navigation在React Native專案中安裝。所以我們需要cmd指令進入專案資料夾之後進行如下命令:
npm install --save react-navigation 下載react-navigation
接下來,安裝react-native-gesture-handler
npm install --save react-native-gesture-handler
連結所有本機依賴項
react-native link react-native-gesture-handler
ios的同學就不需要這麼做了……
要完成針對Android的react-native-gesture-handler的安裝,請務必對以下內容進行必要的修改MainActivity.java
:
import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivityDelegate; import com.facebook.react.ReactRootView; import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; public class MainActivity extends ReactActivity { /** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. */ @Override protected String getMainComponentName() { return "NavigationDemo"; } @Override protected ReactActivityDelegate createReactActivityDelegate() { return new ReactActivityDelegate(this, getMainComponentName()) { @Override protected ReactRootView createRootView() { return new RNGestureHandlerEnabledRootView(MainActivity.this); } }; } }
到此就可以安心的使用react-navigation了,本人之前沒有這樣的步驟去做,所以出現了幾次問題,切記一定要按照這樣的步驟去安裝!
範例解析:
import React from 'react'; import { Button, View, Text } from 'react-native'; import { createStackNavigator, createAppContainer } from 'react-navigation'; // Version can be specified in package.json class HomeScreen extends React.Component { render() { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Home Screen</Text> <Button title="Go to Details" onPress={() => this.props.navigation.navigate('Details')} /> </View> ); } } class DetailsScreen extends React.Component { render() { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Details Screen</Text> <Button title="Go to Details" //這裡的push相當於跳轉的時候不管當前棧裡有沒有該例項都會重新建立一個新的 onPress={() => this.props.navigation.push('Details')} /> </View> ); } } const RootStack = createStackNavigator( { Home: HomeScreen, Details: DetailsScreen, }, { initialRouteName: 'Home', } ); const AppContainer = createAppContainer(RootStack); export default class App extends React.Component { render() { return <AppContainer />; } }
這裡先貼出來程式碼範例
其實有點基礎的不難看出來,程式的入口是在App並且返回渲染了AppContainer的物件,並且這個物件通過createAppContainer返回StackNavigation,對於createAppContainer這個方法網上沒有太多的資料,開啟原始碼解釋如下:
Create an app container to wrap the root navigator
建立一個應用程式容器來包裝根導航器
字面上的理解比較容易就是建立一個容器來承載StackNavigation導航器,那這個導航器是什麼?
程式碼裡面分兩個部分,第一個部分是包含所有介面的元件集合,另一個部分是宣告我們初始化的介面元件是哪一個,看到這裡我們應該知道了,範例中我們聲明瞭兩個介面元件,Home 和 Details ,並且宣告初始化的路由名字是Home,所以開啟介面的首先會進入Home介面,其實這有點像註冊路由一樣,我們要把設計到的介面元件註冊到路由裡面,這樣我們才會navigation的時候才會找得到它。
該範例執行結果如下:
我們看到當前的介面確實是Home Screen,並且點選按鈕會開啟Details介面,返回箭頭會直接返回Home,這只是一個簡單的跳轉邏輯,我們需要做一些更改,怎麼改呢?我們可以嘗試一下在Details Screen裡面再放入一下Button,細心地朋友看到了上面程式碼中我們已經加入了,並且跳轉的時候我們還是跳轉到當前並且是push的,效果會怎麼樣呢,我已經給了註釋,結果卻是會重新開啟這個Derails介面,此時的棧中就兩個Details例項了,這是不是跟Android的啟動模式相似呢,安卓預設的啟動模式standard就是這樣的效果,但是如果我們不用push,還是navigation的話,結局是什麼樣呢?結果就是沒有任何反應,那Android的啟動模式可以做到類似的效果,唯一的不同點就是Android會走特定的生命週期方法。
goBack
堆疊導航器提供的標題將在可以從活動螢幕返回時自動包含後退按鈕(如果導航堆疊中只有一個螢幕,則沒有任何內容可以返回,因此沒有返回鍵)。
有的時候我們希望能夠主動觸發此行為,我們就可以使用this.props.navigation.goBack();
。
class DetailsScreen extends React.Component { render() { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Details Screen</Text> <Button title="Go to Details... again" onPress={() => this.props.navigation.push('Details')} /> <Button title="Go to Home" onPress={() => this.props.navigation.navigate('Home')} /> <Button title="Go back" onPress={() => this.props.navigation.goBack()} /> </View> ); } }
這裡面我們發現回到Home我們是直接navigation的,看看效果是不是跟Android的啟動模式SingleTask很類似呢,對,就是這樣,那我們也可以另外一種方式也可以達到這個效果navigation.popToTop()。
傳遞引數
導航跳轉我們搞定了,接下來我們要傳遞引數,介面與介面之間傳遞引數是必不可少的操作。
傳遞引數是在我們navigation的時候多加一個引數即可,this.props.navigation.navigate('routeName',{key:value}),格式就是這樣,我們看一下程式碼:
這裡我們只是傳遞了兩個引數itemId和otherParam,那在DetailsScreen我們怎麼去接收呢,程式碼如下:
其實方式很簡單,跟map的操作方式很像。
如果你想通過道具直接訪問params(例如。this.props.itemId
)而不是this.props.navigation.getParam
,那麼你可以使用社群開發的react-navigation-props-mapper包。
配置標題欄
現在看我們的介面是不是很枯燥無味,導航欄上面什麼也沒有,這個時候我們可以新增我們自己的介面標題。
這個時候我們需要使用到navigationOptions這個屬性來配置標題顯示。
如上圖所示的配置即可,然後執行我們會發現標題有了:
createStackNavigator 預設情況下使用平臺約定,因此在iOS上標題將居中,而在Android上它將是左對齊的。