React Native自定义路由管理

1,自定义路由

众所周知,无论是在原生Android仍是iOS,它们都有一个默认的路由路由栈管理类。因为React Native官方没有提供路由管理的组件,因此咱们须要使用react-navigation插件提供的Stack.Navigator组件来管理路由。react

Stack.Navigator使用的命名路由,所谓命名路由,指的是路由须要先声明而后才能使用。为了方便管理路由页面,咱们会将路由放到一个统一的位置,好比screens包下,以下所示。
在这里插入图片描述npm

而后,咱们在项目的screens/index.js文件中新建一个常量,主要用来管理声明的路由,以下所示。函数

export const stacks = [
  {
    name: 'AllMovieScreen',
    component: AllMovieScreen,
    options: {headerShown: false},
  },
  {
    name: 'CitySelectScreen',
    component: CitySelectScreen,
    options: {title: '选择城市'},
  },
  …. //省略其余路由页面
];

而后,咱们再新建一个MainStackScreen.js文件,用来实现路由的跳转、返回等操做。同时,MainStackScreen类的另外一个做用是统一导航栏的样式,代码以下所示。工具

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;

在上面的代码,咱们建立了一个creens/index.js文件来申明应用的路由,而后在MainStackScreen 类中使用map循环完成路由的注册。能够看到,通过上面的处理后,路由管理是很是清晰的,当有新的页面时只须要往creens/index.js文件中添加路由便可。spa

2,Tab导航

在React Native应用开发中,react-navigation除了提供路由管理功能外,还支持Tab导航和Drawer导航。而且,在最新的版本中,Tab导航、Drawer导航和Stack导航所依赖的库是分开的,因此在开发过程当中须要单独安装。插件

对于Tab导航来讲,须要在项目中安装Tab导航须要的bottom-tabs库,命令以下。code

npm install @react-navigation/bottom-tabs

建立Tab导航时须要用到createBottomTabNavigator()方法,它须要提供导航器和路由两个属性,分别对应Tab.Navigator和Tab.Screen两个组件,最后还须要使用NavigationContainer组件包裹它们,以下所示。component

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插件还提供了不少其余有用的组件和属性,开发者能够根据须要进行选择。运行上面的代码,效果下图所示。
在这里插入图片描述图片

3,数据回传

有时候,咱们有这样一种需求:跳转到下一个页面,并在下一个页面选择了数据后进行回传。好比:
在这里插入图片描述ci

在上面的场景中,咱们须要对活动列表进行筛选,那么在跳转到活动筛选页面后,须要回传选中的活动类型,对于这种场景,咱们须要对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>
        ),
      };
    },
  }

同时,活动筛选页面的数据是由活动列表页面传递过来的。因此在使用的时候,只须要使用上文封装好的路由工具执行跳转操做便可,代码以下。

navigate('SelectorScreen', {
      values: categories.map(c => c.andGroupName),
      defaultValues: categoryName,
      onConfirm: changeCategory,
    });

能够看到,为了获取筛选页面选择的数据,咱们在跳转的时候定义了一个onConfirm回调函数。接着,咱们在新建的活动筛选页面接收上一个页面传递过来的活动数据并使用列表展现出来便可,以下所示。

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;

选择完活动类型以后,如何将选择的结果返回给上一个页面呢。此时就用到了前文定义的onConfirm回调函数,以下所示。

const {values = [], defaultValues = [], onConfirm} =route.params || {};

const _onRightPress = () => {
    onConfirm(selected);        //onConfirm回调函数回传数据
    navigation.goBack();
 };
相关文章
相关标签/搜索