使用 react-navigation 5 搭建 React Native App 页面导航结构

1,780 阅读3分钟

react navigation是一个用于帮助我们创建 React Native App 的导航结构的库。

首先我们需要一个导航容器包裹我们的应用。

/* 安装这个包 */
npm i -S @react-navigation/native

在项目下建立 src 文件夹,src 文件夹下建立 AppPage.js。

import React from 'react';
import {NavigationContainer} from '@react-navigation/native';

export default function AppPage() {
  return <NavigationContainer />;
}

将项目根目录下的 App.js 内代码清空,将上面的代码导入进来。

import React from 'react';
import AppNavigator from './src/AppPage';

class App extends React.PureComponent {
  render() {
    return <AppNavigator />;
  }
}

export default App;

到这步,页面还是空白的,因为我们还没有加入导航。下面我们让它有点东西。

先安装接下来需要的包

npm i -S @react-navigation/stack @react-native-community/masked-view react-native-safe-area-context  react-native-gesture-handler react-native-screens

/* 装完了 iOS 需要进行以下操作 */
cd ios
pod install

自行搭建测试页面,马上用到。

都搞定后,修改 src/AppPage.js 代码,替换成下面的代码。

import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import IndexPage from './pages/IndexPage';

const Stack = createStackNavigator();

export default function AppPage() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="首页">
        <Stack.Screen name="首页" component={IndexPage} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

运行模拟器,如果可以看到这个样子,那么我们的 hello world 就完成了。

接下来,我们来创建一个带有 tabbar 的导航。

安装所需要的包

npm i -S @react-navigation/bottom-tabs

修改 src/AppPage.js

import React from 'react';
import {Image} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
// import {createStackNavigator} from '@react-navigation/stack';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import IndexPage from './pages/IndexPage';
import MyPage from './pages/MyPage';
import IndexIcon from './res/tabs/tab_bar_icon_home_n.png';
import IndexSelectedIcon from './res/tabs/tab_bar_icon_home_s.png';
import MyIcon from './res/tabs/tab_bar_icon_my_n.png';
import MySelectedIcon from './res/tabs/tab_bar_icon_my_s.png';

const tabbarConfig = [
  {
    icon: IndexIcon,
    selectedIcon: IndexSelectedIcon,
    title: '首页',
  },
  {
    icon: MyIcon,
    selectedIcon: MySelectedIcon,
    title: '我的',
  },
];
const Tab = createBottomTabNavigator();

export default function AppPage() {
  return (
    <NavigationContainer>
      <Tab.Navigator
        initialRouteName="首页"
        screenOptions={({route}) => ({
          tabBarIcon: ({focused, color, size}) => {
            let icon = '';
            tabbarConfig &&
              tabbarConfig.forEach(tabbar => {
                if (route.name === tabbar.title) {
                  icon = focused ? tabbar.selectedIcon : tabbar.icon;
                }
              });
            return (
              <Image
                source={icon}
                resizeMode="cover"
                style={{width: 20, height: 20}}
              />
            );
          },
        })}
        tabBarOptions={{
          inactiveTintColor: '#666',
        }}>
        <Tab.Screen name="首页" component={IndexPage} />
        <Tab.Screen name="我的" component={MyPage} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

完成后,页面如下图所示。(tabbar 图标需要自己找资源加入)

接下来让页面跳转进详情页,自行新建个详情页,然后在首页的代码加入这个按钮。

<Button
  title="go to Detail"
  onPress={() => this.props.navigation.push('详情')}
 />

修改 src/AppPage.js ,把首页和详情页合并成一个 stack。

/* 加入之前的 stack */
import {createStackNavigator} from '@react-navigation/stack';
const Stack = createStackNavigator();

function StackScreen() {
 return (
   <Stack.Navigator>
     <Stack.Screen name="首页" component={IndexPage} />
     <Stack.Screen name="详情" component={DetailPage} />
   </Stack.Navigator>
 );
}

/* 修改第一个 Tab */
<Tab.Screen name="首页" component={StackScreen} />

修改后结果,点击按钮,进入了 详情页。

但是通常我们详情页是没有底部 tabbar 的,所以我们还得再改造下。

还是修改 src/AppPage.js

/* 把 tab 变成函数式组件 */
function HomeScreen() {
  return (
    <Tab.Navigator
      initialRouteName="首页"
      screenOptions={({route}) => ({
        tabBarIcon: ({focused, color, size}) => {
          let icon = '';
          tabbarConfig &&
            tabbarConfig.forEach(tabbar => {
              if (route.name === tabbar.title) {
                icon = focused ? tabbar.selectedIcon : tabbar.icon;
              }
            });
          return (
            <Image
              source={icon}
              resizeMode="cover"
              style={{width: 20, height: 20}}
            />
          );
        },
      })}
      tabBarOptions={{
        inactiveTintColor: '#666',
      }}>
      <Tab.Screen name="首页" component={IndexPage} />
      <Tab.Screen name="我的" component={MyPage} />
    </Tab.Navigator>
  );
}

/* 换回之前的 stack */
export default function AppPage() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="首页" component={HomeScreen} />
        <Stack.Screen name="详情" component={DetailPage} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

修改后,进入详情页,就不会有底部的 tabbar 了。

很多时候,我们并不希望首页顶部有 Navbar,可以这么设置。

<Stack.Navigator headerMode="none">

但这么做所有的页面都没有顶部标题栏了。

 <Stack.Screen name="首页" 
               options={{headerShown:false}}
               component={IndexPage}
 />

这样就能实现首页不要标题导航栏的需求了。