简介
一般情况下,使用React Navigation的时候,我们总是从某个属于React Navigation导航栈的屏幕(或者叫做路由)组件的内部发起导航,这种情况下,因为我们有this.props.navigation
可用,所以发起导航不是什么问题。但是在有些时候,比如我们对通用业务逻辑进行了封装并且需要在这些逻辑中发起屏幕切换,而这些封装后的逻辑不属于任何一个React Navigation导航栈的屏幕组件,而是位于某一个其他类中,那么这时候我们怎么办呢 ?
React Navigation官方网站提供了一种方法,其思路是记录所用导航栈到一个全局变量,然后封装一个导航服务,该服务利用这个导航栈全局变量发起屏幕切换。我们使用例子代码演示该方法。
导航服务封装
import {NavigationActions} from 'react-navigation';
// reference : https://reactnavigation.org/docs/navigating-without-navigation-prop.html
// 该服务作为单例模式使用,用于记录顶层导航器,这样在应用的各个部分,各个屏幕组件内部,
// 或者任何屏幕组件之外的其他服务逻辑/工具逻辑中,都可以使用该服务的 navigate() 方法导航到目标屏幕,
// 类似于在某个屏幕组件中使用 this.props.navigation.navigate 函数进行的屏幕切换
// 用于记录所使用的导航器
let _navigator;
/**
* 记录所使用的导航器
* @param navigatorRef
*/
function setTopLevelNavigator(navigatorRef) {
_navigator = navigatorRef;
}
/**
* 导航到目标路由/屏幕
* @param routeName
* @param params
*/
function navigate(routeName, params) {
_navigator.dispatch(
NavigationActions.navigate({
type: NavigationActions.NAVIGATE,
routeName,
params,
})
);
}
export default {
navigate,
setTopLevelNavigator,
};
应用组件中记录所用导航栈
import React, {Component} from 'react';
import {StackNavigator} from 'react-navigation';
import navigationService from './NavigationService';
const rootStack = StackNavigator({
// ... 省略具体实现
});
export default class App extends Component {
// ... 其他代码
render() {
return <rootStack ref={navigatorRef => {
navigationService.setTopLevelNavigator(navigatorRef);
}}
/>;
}
}
// ... 其他代码
使用导航服务在任意位置发起屏幕切换
// 比如在某个服务逻辑封装类中
import navigationService from "../NavigationService";
navigationService.navigate('LoginScreen', {})