React Native自定義路由管理的深入理解
1、自定義路由
眾所周知,不管是在原生Android還是iOS,它們都有一個默認的路由路由棧管理類。由于React Native官方?jīng)]有提供路由管理的組件,所以我們需要使用react-navigation插件提供的Stack.Navigator組件來管理路由。
Stack.Navigator使用的命名路由,所謂命名路由,指的是路由需要先聲明然后才能使用。為了方便管理路由頁面,我們會將路由放到一個統(tǒng)一的位置,比如screens包下,如下所示。

然后,我們在項目的screens/index.js文件中新建一個常量,主要用來管理聲明的路由,如下所示。
export const stacks = [
{
name: 'AllMovieScreen',
component: AllMovieScreen,
options: {headerShown: false},
},
{
name: 'CitySelectScreen',
component: CitySelectScreen,
options: {title: '選擇城市'},
},
…. //省略其他路由頁面
];
然后,我們再新建一個MainStackScreen.js文件,用來實現(xiàn)路由的跳轉(zhuǎn)、返回等操作。同時,MainStackScreen類的另一個作用是統(tǒng)一導航欄的樣式,代碼如下所示。
onst MainStack = createStackNavigator();
function MainStackScreen({navigation}) {
return (
<MainStack.Navigator
initialRouteName="App"
screenOptions={{
headerTitleAlign: 'center',
headerStyle: {
shadowOffset: {width: 0, height: 0},
shadowColor: '#E5E5E5',
backgroundColor: '#fff',
},
gestureEnabled: true,
headerBackTitleVisible: false,
headerLeft: () => (
<TouchableOpacity
onPress={() => navigation.goBack()}
style={{padding: 10, paddingRight: 30}}>
<Icon name="chevron-thin-left" size={20} color="#222222" />
</TouchableOpacity>),
}}>
<MainStack.Screen
name="App"
component={BottomTab}
options={{headerShown: false}}/>
{stacks.map((item, index) => (
<MainStack.Screen
key={index.toString()}
name={item.name}
component={item.component}
options={item.options}/>
))}
</MainStack.Navigator>
);
}
export default MainStackScreen;
在上面的代碼,我們創(chuàng)建了一個creens/index.js文件來申明應用的路由,然后在MainStackScreen 類中使用map循環(huán)完成路由的注冊??梢钥吹?,經(jīng)過上面的處理后,路由管理是非常清晰的,當有新的頁面時只需要往creens/index.js文件中添加路由即可。
2、Tab導航
在React Native應用開發(fā)中,react-navigation除了提供路由管理功能外,還支持Tab導航和Drawer導航。并且,在最新的版本中,Tab導航、Drawer導航和Stack導航所依賴的庫是分開的,所以在開發(fā)過程中需要單獨安裝。
對于Tab導航來說,需要在項目中安裝Tab導航需要的bottom-tabs庫,命令如下。
npm install @react-navigation/bottom-tabs
創(chuàng)建Tab導航時需要用到createBottomTabNavigator()方法,它需要提供導航器和路由兩個屬性,分別對應Tab.Navigator和Tab.Screen兩個組件,最后還需要使用NavigationContainer組件包裹它們,如下所示。
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {NavigationContainer} from '@react-navigation/native';
const BottomTabs = createBottomTabNavigator();
export default function BottomTabScreen() {
return (
<NavigationContainer>
<BottomTabs.Navigator
initialRouteName="Home"
screenOptions={({route}) => ({
tabBarIcon: ({focused}) => {
return (
<Image source={ focused? tabImage[`${route.name}_active`]
: tabImage[route.name]
}
style={{width: 26, height: 26}}/>
); }})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
style: {
backgroundColor: '#fff',
},
}}>
<BottomTabs.Screen
name="Home"
component={HomeScreen}
options={{
tabBarLabel: '電影',
}}/>
…. //省略其他代碼
<BottomTabs.Screen
name="Mine"
component={MineScreen}
options={{
tabBarLabel: '我的',
}}/>
</BottomTabs.Navigator>
</NavigationContainer>
);
}
同時,bottom-tabs插件還提供了很多其他有用的組件和屬性,開發(fā)者可以根據(jù)需要進行選擇。運行上面的代碼,效果下圖所示。

3、數(shù)據(jù)回傳
有時候,我們有這樣一種需求:跳轉(zhuǎn)到下一個頁面,并在下一個頁面選擇了數(shù)據(jù)后進行回傳。比如:

在上面的場景中,我們需要對活動列表進行篩選,那么在跳轉(zhuǎn)到活動篩選頁面后,需要回傳選中的活動類型,對于這種場景,我們需要對react-navigation進行怎樣的處理呢?
首先,我們在screens/index.js文件中注冊活動類型頁面,如下所示。
{
name: 'SelectorScreen',
component: SelectorScreen,
options: nav => {
const {route} = nav;
const {params = {}} = route;
const {title = '活動類型', onRightPress = () => {}} = params;
return {
title,
headerRight: () => (
<TouchableOpacity
onPress={onRightPress}
style={styles.button}>
<Text style={{color: '#fff', fontSize: 14}}>確定</Text>
</TouchableOpacity>
),
};
},
}
同時,活動篩選頁面的數(shù)據(jù)是由活動列表頁面?zhèn)鬟f過來的。所以在使用的時候,只需要使用上文封裝好的路由工具執(zhí)行跳轉(zhuǎn)操作即可,代碼如下。
navigate('SelectorScreen', {
values: categories.map(c => c.andGroupName),
defaultValues: categoryName,
onConfirm: changeCategory,
});
可以看到,為了獲取篩選頁面選擇的數(shù)據(jù),我們在跳轉(zhuǎn)的時候定義了一個onConfirm回調(diào)函數(shù)。接著,我們在新建的活動篩選頁面接收上一個頁面?zhèn)鬟f過來的活動數(shù)據(jù)并使用列表展示出來即可,如下所示。
function SelectorScreen({navigation, route}) {
const {values = [], defaultValues = [], onConfirm} =route.params || {};
const [selected, setSelected] = useState(defaultValues);
const _onRightPress = () => {
onConfirm(selected);
navigation.goBack();
};
useEffect(() => {
navigation.setParams({onRightPress: _onRightPress});
}, [selected]);
const onPressItem = val => {
let arr = [];
arr = [val];
setSelected(arr);
};
const renderItem = ({item}) => {
const renderRight = () => {
const isSelected = selected.includes(item);
return (
<ListItem
text={item}
renderRight={renderRight}
onPress={() => onPressItem(item)} />
);
};
return (
<View style={styles.bg}>
<FlatList
keyExtractor={(item, index) => item + index}
data={values}
renderItem={renderItem}
ListFooterComponent={<View height={120} />} />
</View>
);
};
const styles = StyleSheet.create({
…. //省略樣式代碼
});
export default SelectorScreen;
選擇完活動類型之后,如何將選擇的結(jié)果返回給上一個頁面呢。此時就用到了前文定義的onConfirm回調(diào)函數(shù),如下所示。
const {values = [], defaultValues = [], onConfirm} =route.params || {};
const _onRightPress = () => {
onConfirm(selected); //onConfirm回調(diào)函數(shù)回傳數(shù)據(jù)
navigation.goBack();
};
總結(jié)
到此這篇關于React Native自定義路由管理的文章就介紹到這了,更多相關React Native自定義路由管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
react-redux多個組件數(shù)據(jù)共享的方法
這篇文章主要介紹了react-redux多個組件數(shù)據(jù)共享的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08
webpack 2.x配置reactjs基本開發(fā)環(huán)境詳解
本篇文章主要介紹了webpack 2.x配置reactjs基本開發(fā)環(huán)境詳解,具有一定的參考價值,有興趣的可以了解一下2017-08-08
詳解React開發(fā)中使用require.ensure()按需加載ES6組件
本篇文章主要介紹了詳解React開發(fā)中使用require.ensure()按需加載ES6組件,非常具有實用價值,需要的朋友可以參考下2017-05-05

