RN-app的基础框架

目录

这份文档纯属原创,在查阅众多资料后凝聚而成。将从前言、react-navigation5.x /6.x 以及踩坑点讲述。

前言

以原创项目为例讲解使用RN使用React-navigation如果去搭建一个app框架,包括createStackNavigator、createBottomTabNavigator的嵌套、路由设置、路由跳转(传参以及如何接收参数)以及踩坑。其中会涉及到一些api,具体操作请详见 React-navigation官网

github地址 react-native-myapp-tonue

react-navigation5.x /6.x

createBottomTabNavigator (@react-navigation/bottom-tabs)

注意:
createBottomTabNavigator如果是从@react-navigation/bottom-tabs引入的话用法与4.x是不同的。之前4.x的语法是createBottomTabNavigator(RouteConfigs, BottomTabNavigatorConfig)。而5.x则是通过Navigator包裹Screen实现的。
除此之外,createBottomTabNavigator使用需要react-native-screens、react-native-safe-area-context、react-native-safe-area-view相关依赖。

// 引入NavigationContainer、createBottomTabNavigator
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
// 创建底部tab
// 后续根据需求新增tab
const BottomTab = createBottomTabNavigator();
const App = () => {
  return (
	  <NavigationContainer>
	    <BottomTab.Navigator
	      screenOptions={() => ({
	        tabBarActiveTintColor: '#FF8E4A',
	        tabBarInactiveTintColor: '#666666',
	        headerShown: false // 不展示标题栏
	      })}
	      tabBar={(props) => <TabBar {...props} />}
	    >
	      <BottomTab.Screen name='Toune' component={TouneStackScreen} />
	      {/* <BottomTab.Screen name='Views' component={TouneStackScreen} /> */}
	    </BottomTab.Navigator>
    </NavigationContainer>
  )
}
export default App;

如果想用官方底部tab样式,那么就不需要去关注screenOptions、tabBar这些属性,这里还需注意一点是,5.x版本Navigator的tabBarOptions与screenOptions合并了起来。
如果想自己去设置底部栏的样式,那么就需要去重点关注tabBar这个属性和screenOptions这个属性。

screenOptions
可以设置是否展示导航栏、并且定义tab激活状态的样式以及未激活状态的样式等等。但是如果是完全重写底部tab的样式的话可以选择自定义组件。

tabBar
tabBar={(props) => <TabBar {…props} /> 可以利用这个属性去重定义tab样式。这里的props是一个对象,可以传递navigation,state以及descriptors。navigation中包括一些api,比如navigate、push等函数。state中包含定义的路由以及激活状态下的路由索引。descriptors包含一些tab的其余属性。比如可以利用descriptors[route.key]方法查找每一个路由或者tab定义的options。

// 渲染自定义底部栏
const TabBar = ({ navigation, descriptors, state }) => {
  const { routes, index: activeRouteIndex } = state;

  return (
    <View style={Styles.container}>
      {routes.map((route, routeIndex) => {
        const { options: { tabBarActiveTintColor, tabBarInactiveTintColor } } = descriptors[route.key];
        const isRouteActive = routeIndex === activeRouteIndex;
        const tintColor = isRouteActive ? tabBarActiveTintColor : tabBarInactiveTintColor;
        // console.log(options);
        const onPress = () => {
          const event = navigation.emit({
            type: 'tabPress',
            target: route.key,
            canPreventDefault: true,
          });
          if (!isRouteActive && !event.defaultPrevented) {
            // The `merge: true` option makes sure that the params inside the tab screen are preserved
            navigation.navigate({ name: route.name, merge: true });
          }
        }
        const onLongPress = () => {
          navigation.emit({
            type: 'tabLongPress',
            target: route.key,
          });
        };
        return (
          <TouchableNativeFeedback
            key={routeIndex}
            style={Styles.tabButton}
            onPress={onPress}
            onLongPress={onLongPress}
          >
            <View style={Styles.tabButton}>
              <Text style={{ color: tintColor }}>{route.name}</Text>
            </View>
          </TouchableNativeFeedback>
        )
      })}
    </View>
  )
}

可以将自定义组件代码和上面的代码结合起来看,也可以去仓库将代码copy下来自己试试。

createStackNavigator(@react-navigation/stack)

在定义bottomtab的时候嵌套了stack,其中TouneStackScreen也是需要引入的。

<BottomTab.Screen name=‘Toune’ component={TouneStackScreen} />

import * as React from "react";
import { createStackNavigator } from '@react-navigation/stack';
import Toune from '../Views/Tonue/index';
import ProgressDemo from '../Views/Tonue/progressDemo';
import DatePickerDemo from '../Views/Tonue/DatePickerDemo';

// 定义路由
const TouneStack = createStackNavigator();
const TouneStackScreen = () => {
  return (
    <TouneStack.Navigator
      screenOptions={{
        headerShown: false // 不展示标题栏
      }}>
      <TouneStack.Screen name='TouneScreen' component={Toune} />
      <TouneStack.Screen name='ProgressDemo' component={ProgressDemo} />
      <TouneStack.Screen name='DatePickerDemo' component={DatePickerDemo} />
    </TouneStack.Navigator>
  )
}
export default TouneStackScreen;

用法基本与createBottomTabNavigator类似。

StackNavigator与BottomTabNavigator的互相嵌套

StackNavigator与BottomTabNavigator可以互相嵌套,也就是说StackNavigator可以去嵌套BottomTabNavigator,相反BottomTabNavigator也可以去嵌套StackNavigator。但两者有着一些区别。

BottomTabNavigator嵌套StackNavigator


const BottomTab = createBottomTabNavigator();
const App = () => {
  return (
	  <NavigationContainer>
	    <BottomTab.Navigator>
	      <BottomTab.Screen name='Toune' component={TouneStackScreen} />
	      {/* <BottomTab.Screen name='Views' component={TouneStackScreen} /> */}
	    </BottomTab.Navigator>
	  </NavigationContainer>
  )
}

StackNavigator嵌套BottomTabNavigator

const Stack = createStackNavigator();
const Appv2 = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name='mainRoute' component={App} />
        <Stack.Screen name='ProgressDemo' component={ProgressDemo} />
      </Stack.Navigator>
    </NavigationContainer>
  )
}

两者区别:
比如你的需求是不想让跳转后的次级页面展示BottomTab,你就可以用StackNavigator嵌套BottomTabNavigator的方法,将次级页面ProgressDemo不用BottomTabNavigator包裹。

路由跳转(props.route.params)

路由传参接收:
在项目中安装的@react-navigation/stack和@react-navigation/bottom-tabs是6.x版本的,与5.x相比路由传参接收有些许不同。

用react-navigation做路由管理时,一个页面向另外一个页面跳转可以使用navigate,也可以使用push,这些api在官网都有详细的介绍。但是接收路由传参却不能使用常规的navigation.state.params或者getParams这两个api,因为console.log后发现props.navigation没有这两个属性。但是打印props就能发现它提供了一个新的属性props.route,可以利用props.route.params去获取传参。

// 前一个页面
  jumpToPage = (page, params) => {
    console.log(page);
    const { navigate } = this.props.navigation;
    console.log(params, 'params');
    navigate(`${page}`, params);
  }
// 后一个页面
  this.navBarTitle = `${props.route.params?.['tonue']}组件详情`;

踩坑

在构建该项目可能不会像网上说的那么easy,比如明明用react-native init name --version 初始化了app,但是npx react-native start的时候又会出现unexpected token这类错,后面才发现版本号如果指定0.60.0或者0.61.5都会报这个问题。又比如在react-native 6 以上版本中安装react-native-screens、react-native-safe-area-context、react-native-safe-area-view后又会报错。查了很多资料也试了很多未果之后又去react-native init name --version了一个新的版本,我以为会成功,但是安装完 react-native-reanimated后,重新执行npx react-native run-android后出现了报错。
在这里插入图片描述
我删除了react-native-reanimated依赖,将 react-native-safe-area-context 从4.2.5降级到3.2.5才ok。
Alt

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值