命令安裝
// 安裝基礎包 ^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<RootStackParamList>();
const Navigator = Stack.Navigator;
const Screen = Stack.Screen;
路由列表
// 路由頁面配置
<NavigationContainer>
<Stack.Navigator
initialRouteName={Views.Home}
screenOptions={{
headerShadowVisible: false, // android 導航去陰影
headerTitleAlign: 'center', // 標題居中
// 設定導航欄字型樣式
headerTitleStyle: {
fontSize: 17,
color: '#333333',
fontFamily: 'PingFangSC-Semibold',
fontWeight: '700',
},
headerLeft: () => headerLeft(),
}}
>
<Stack.Screen
name={Views.Home}
component={Home}
options={{ title: '每日任務' }}
/>
<Stack.Screen
name={Views.NewTask}
component={NewTask}
options={{ title: '新手任務' }}
/>
<Stack.Screen
name={Views.Redeem}
component={Redeem}
options={{ title: '積分兌換' }}
/>
<Stack.Screen
name={Views.Rule}
component={Rule}
options={{ title: '積分兌換規則' }}
/>
</Stack.Navigator>
</NavigationContainer>
屬性引數詳解
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<RootStackParamList>;
// 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 (
<TouchableOpacity
onPress={() => {
// 如果無法在使用路由退出後 呼叫native協議關閉當前RN容器
navigation.canGoBack() ? navigation.goBack() : Alert.alert('路由首頁');
}}
>
<Image
style={{
height: 25,
width: 25,
}}
source={require('./images/back.png')}
/>
</TouchableOpacity>
);
};
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 (
<TouchableOpacity
onPress={() => {
navigation.navigate(Views.Rule);
}}
>
<Text style={styles.headerRight}>兌換規則</Text>
</TouchableOpacity>
);
};
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<RootRouteType>();
useLayoutEffect(() => {
// 初始化賦值
navigation.setParams({ testParam: 'test' });
// 路由返回時觸發呼叫父頁面傳入的callback方法,模擬路由回撥
return () => {
route.params?.callback();
};
}, []);
// 路由引數獲取
const getParams = () => {
// 頁面獲取到的路由引數如下:(圖二所示)有父頁面路由跳轉的傳參,有本頁面類自己註冊的路由頁面引數testParam
const params = route.params;
console.log(params);
};
}
export default NewTask;
圖一
圖二
2、其他
總結
以上是本人業務開發中常用的功能總結,有更深層次的使用,歡迎留言;總結不易,轉載請賦原文連結。