命令安装
// 安装基础包 ^6.0.6
yarn add @react-navigation/native -S
// 安装路由包 ^6.2.5
yarn add @react-navigation/native-stack -S
//RN版本0.65.1 React版本17.0.2
"react": "17.0.2",
"react-native": "0.65.1",
路由配置
包引用
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
const Navigator = Stack.Navigator;
const Screen = Stack.Screen;
路由列表
// 路由页面配置
headerLeft(),
}}
>
属性参数详解
Stack.Navigator
导航全局配置,再次配置的参数在所有路由页面的导航上面全部生效,具体属性如下
initialRouteName: //指定路由首页 类比React的跟路由页面
// 用于导航器中屏幕的默认选项
screenOptions: {
headerShadowVisible: false, // android 导航去阴影 默认true开启状态
headerTitleAlign: 'center', // 标题居中 默认 'left'
headerTitle: '标题', //全局标题 在此设置是不生效的 默认展示路由页面的name
// 设置导航栏字体样式
headerTitleStyle: {
fontSize: 17,
color: '#333333',
fontFamily: 'PingFangSC-Semibold',
fontWeight: '700',
},
headerTintColor: 'red', // 导航栏字体颜色设置 如果设置了headerTitleStyle则此处设置不生效
statusBarStyle: 'light' //"inverted" | "auto" | "light" | "dark" | undefined 状态栏配置
headerLeft: React.ReactNode, //导航左侧区域按钮配置 不配置默认展示左箭头返回图标
headerRight: React.ReactNode //导航右侧区域配置 默认无
}
以上基础配置基本上能满足绝大多数业务的日常开发了
Stack.Screen
页面导航配置,此处的配置会覆盖全局配置,具体属性参数如下:
const Home = lazy(() => import('./views/home'));
name= 'Home' //指定的路由页面的名称 必填属性
component= Home // 路由React页面挂载 必填属性
initialParams={{ itemId: 42 }} //页面初始化参数
// 路由页面导航配置 此处的配置会覆盖全局的screenOptions
options={{
title: '积分兑换规则', //路由页面标题
headerLeft: React.ReactNode, //导航左侧区域按钮配置 不配置默认展示左箭头返回图标
headerRight: React.ReactNode //导航右侧区域配置 默认无
}}
路由使用
由于新版本的RN基本上都采用Hooks+TypeScript的方式来开发,在使用时好多都需要做类型声明
声明文件
首先添加一个全局声明文件,方便后面的自定义hooks(下面会详细介绍)的调用;
本人的工程开发目录如下:
首先在types下面加一个全局的ts声明文件index.ts 内容如下:
import { RouteProp } from '@react-navigation/native'; // 获取route的props
// 枚举出来所有的路由页面的Name
export enum Views {
Home = 'Home',
NewTask = 'NewTask',
Redeem = 'Redeem',
Rule = 'Rule',
}
interface NewTaskProps {
title: string;
action: string;
funcName: string;
params: any;
}
// 定义每个路由页面需要传达到下个页面的参数 在目的页面里面声明要接受的参数
export type RootStackParamList = {
[Views.Home]: undefined;
[Views.NewTask]:
| {
/** @description 声明往子组件里面的传参 */
item: NewTaskProps;
callback: () => void;
}
| undefined;
[Views.Redeem]:
| {
/** @description 监听页面返回回调父页面 */ callback: () => void;
}
| undefined;
[Views.Rule]: undefined;
};
// 定义声明每个子路由界面接收的具体数据类型useRoute 后面详解使用
export type RootRouteType = RouteProp;
// This registers which makes navigation fully type-safe.
// https://reactnavigation.org/docs/typescript#specifying-default-types-for-usenavigation-link-ref-etc
// 全局声明useNavigation自定义hooks方法的参数
declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList {}
}
}
自定义hooks
目前react-navigation提供了自定义hooks方法useNavigation、useRoute等,重点讲解一下路由的使用
useNavigation
1、返回监听navigation.goBack()
import { useNavigation } from '@react-navigation/native';
// 左侧返回按钮
const headerLeft = () => {
// hooks里面获取导航器对象
const navigation = useNavigation();
return (
{
// 如果无法在使用路由退出后 调用native协议关闭当前RN容器
navigation.canGoBack() ? navigation.goBack() : Alert.alert('路由首页');
}}
>
);
};
2、路由跳转navigation.navigate
import React, { FC } from 'react';
import { useNavigation } from '@react-navigation/native';
import { Views } from '@types'; //此处配置了alias 可以直接使用@
const Home: FC = () => {
// 自定义hooks里面调用导航对象
const navigation = useNavigation();
// 普通不带参数跳转
const jumpNewTask = () => {
//不带参数的普通跳转 如果没有全局的ReactNavigation声明 按文档调用会报如下错误一的问题
navigation.navigate(Views.NewTask);
}
// 带参数跳转
const jumpNewTask = () => {
//如果不再目的页面做入参的声明会有如下报错(错误二)
navigation.navigate(Views.NewTask, {
item: {
title: '弹窗',
action: 'CSTShowDialog',
funcName: 'dialog',
params: {
title: '温馨提示',
content: '请上传证件照,否则发帖需要扣费10元',
btns: [
{ color: '#ff552e', text: '确定' },
{ color: '#000000', text: '取消' },
],
},
},
callback: () => {
// 新手任务返回首页 拉取积分信息
getTaskInfo();
},
});
}
}
报错一
报错二
3、重写导航navigation.setOptions
import React, { FC, useLayoutEffect, useEffect } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native'
const Redeem: FC = () => {
const navigation = useNavigation();
const headerRight = () => {
return (
{
navigation.navigate(Views.Rule);
}}
>
兑换规则
);
};
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => headerRight(),
});
}, []);
}
4、路由页面内赋值参数navigation.setParams
import React, { FC, useLayoutEffect } from 'react';
import { View, Text } from 'react-native';
import { useNavigation } from '@react-navigation/native';
const NewTask: FC = () => {
const navigation = useNavigation();
useLayoutEffect(() => {
// 初始化赋值
navigation.setParams({ testParam: 'test' });
}, []);
}
export default NewTask;
// 页面内赋值一般要使用?:可选参数的方式声明 否则上个页面的路由跳转会报如下错误
//错误声明
[Views.NewTask]:
| {
/** @description 声明往子组件里面的传参 */
item: NewTaskProps;
testParam: string;
callback: () => void;
}
| undefined;
// 正确的声明方式
[Views.NewTask]:
| {
/** @description 声明往子组件里面的传参 */
item: NewTaskProps;
testParam?: string;
callback: () => void;
}
| undefined;
5、其他
其他API暂不做详解
useRoute
路由页面参数接收自定义hooks
1、路由参数接收route.params
import React, { FC, useLayoutEffect } from 'react';
import { View, Text } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import { RootRouteType } from '@types';
const NewTask: FC = () => {
const navigation = useNavigation();
// @react-navigation/native自定义hooks里面获取路由参数对象
// 错误 未声明直接使用报错如下 图一
// const route = useRoute();
// 正确使用方式 先声明后使用RootRouteType如上types里面的声明
const route = useRoute();
useLayoutEffect(() => {
// 初始化赋值
navigation.setParams({ testParam: 'test' });
// 路由返回时触发调用父页面传入的callback方法,模拟路由回调
return () => {
route.params?.callback();
};
}, []);
// 路由参数获取
const getParams = () => {
// 页面获取到的路由参数如下:(图二所示)有父页面路由跳转的传参,有本页面类自己注册的路由页面参数testParam
const params = route.params;
console.log(params);
};
}
export default NewTask;
图一
图二
2、其他
总结
以上是本人业务开发中常用的功能总结,有更深层次的使用,欢迎留言;总结不易,转载请赋原文链接。