1. 背景
通常一个应用不会由单个界面组成,而是由多个模块、多个页面组成。react-navigation的功能就是负责RN导航条管理、页面跳转以及中间的交互过程,这篇文章主要围绕这个方案的使用介绍。
2. 安装
# 项目根目录安装
yarn add react-navigation
# or with npm
# npm install react-navigation
npm install --save react-navigation
npm install --save react-native-gesture-handler
注意:不同RN版本会有特定的配置,例如下面是大于0.60的注意点。
if you're on React Native >= 0.60, you need to disable autolinking for react-native-gesture-handler first.
更详细可参考安装教程
3. 使用
在react-navigation中有以下类型导航器:
- StackNavigator: 类似于普通的Navigator,屏幕上方导航栏;
- TabNavigator: 相当于iOS里面的TabBarController,屏幕下方的标签栏;
- DrawerNavigator: 抽屉效果,侧边滑出;
- SwitchNavigator
- ...
创建
几种导航器的创建方式是相似的,这里以创建 StackNavigator 为例。
现在定义HomeComp组件路由为Home,LoginComp组件路由为Login,LoginComp为默认第一个显示的组件。
# 创建底部标签栏为: const RootStack = createBottomTabNavigator(...)
# 创建测滑为: const RootStack = createDrawerNavigator(...)
# 创建上方导航栏
const RootStack = createStackNavigator(
{
Home:{//路由
screen:HomeComp,//对应组件
},
Login:{
screen:LoginComp
}
},
{
initialRouteName: 'Login', //第一个显示组件页面,填路由
//默认全局配置
// defaultNavigationOptions: {
// headerStyle: {
// backgroundColor: '#f4511e',
// },
// headerTintColor: '#fff',
// headerTitleStyle: {
// fontWeight: 'bold',
// },
// }
}
)
const AppContainer = createAppContainer(RootStack);//创建容器
export default class App extends React.Component<IAppProps> {
render() {
return (
<AppContainer />
)
}
}
跳转&传参
定义好路由之后,我们就可以尝试跳转了。跳转主要用的是StackActions
方法,我们可以通过它传入路由和参数进行跳转。
StackActions.push({routeName, params, action, key})
根据具体业务的不同,会有不同的跳转行为,StackActions跳转行为有下面几种:
方法 | 用法 | 例子 |
---|---|---|
push | 导航到堆栈中的一个新的路由 | [A , B] push C == [A , B , C] |
pop | 返回堆栈中的上一个页面 | [A, B] pop == [A] |
popToTop | 返回堆栈中的第一个页面 | [A, B,C] popToTop == [A] |
replace | 用新路由替换当前路由 | [A , B] replace C == [A , C] |
reset | 擦除导航器状态并将其替换为多个操作的结果 | [A , B] reset C == [C] |
并且需要我们传入对应参数。
参数解释
- routeName:要跳转到的界面的路由名,也就是在createStackNavigator中配置的路由名;
- params:要传递给下一个界面的参数,可选;
- action:如果该界面是一个navigator的话,将运行这个sub-action,可选;
- key:要导航到的路由的可选标识符。 如果已存在,将后退到此路由,可选。
案例
# 跳转Home组件&传入参数:
StackActions.push({routeName:'Home',params:{name:'张三'}})
# or
NavigationActions. navigation({routeName:'Home'})
# or
this.props.navigation.navigate('Home', { /* params go here */ })
# Home组件获取跳转参数
const ops = this.props.navigation.getParam('params')
# or
const ops = this.props.navigation.state.params
除此之外,navigationActions也包含部分跳转方法。
NavigationActions.navigation ({routeName, params, action, key})
方法 | 用法 | 例子 |
---|---|---|
navigation | 跳转到当前堆栈路由里存在的一个页面 | [A , B,C, D] navigate B == [A, B] |
Back | 返回到上一个页面 | [A, B] Back == [A] |
popToTop | 返回堆栈中的第一个页面 | [A, B,C] popToTop == [A] |
Set Params | 设置指定页面的Params | ** |
Init | 初始化一个 state 如果 state 是 undefined | ** |
header bar设置
默认导航跳转的页面是不带头部导航栏的,需要我们在组件里面进行设置。
每个页面组件可以有一个名为navigationOptions
的静态属性,它是一个对象或一个返回包含各种配置选项的对象的函数,下面是一个操作实例。
class Home extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
//title:'标题'
headerTitle: <headerTitle/>,//自定义中间标题控件
headerRight: <LeftButton event={()=>{navigation.getParam('back')}}/>,//自定义左边控件
headerLeft: <RightButton/>,//自定义右边控件
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
};
};
componentDidMount() {
this.props.navigation.setParams({ back: this. _back });
}
_back = () => {
alert('back')
};
}
需要注意的是:
-
由于navigationOptions 是个static方法,不能直接拿到this对象里的方法,需要先通过this.props.navigation.setParams设置,navigationOptions里通过navigation.getParam('back')获取。
-
headerStyle、headerTintColor、headerTitleStyle等属性也可以直接在createStackNavigator全局设置。
模态跳转
如果需要模态跳转则需要修改配置。
const RootStack = createStackNavigator(
{
Main: {
screen: MainStack,
},
MyModal: {
screen: ModalScreen,
},
},
{
mode: 'modal',
headerMode: 'none',
}
);
4. 多模块跳转
通常在同一个模块下面不容易出现路由重名的情况,这种情况通常出现在多个模块开发。并且当跳转只写了一个路由名字时,是不清楚跳转到哪个模块下面的页面,缺乏可读性。因此在react-navigation基础上,笔者团队做了一套简单的处理路由的逻辑。
- 每一个模块下面会有一个routes.ts的文件。在项目初始化时,会获取所有模块下route.ts文件里定义的路由和对应组件,并根据对应模块名字拼接路由路径。例如在home模块目录有个routes.ts。下面的详情路由经过处理后的真实路由为home/homeDetail。
# home模块下router.ts文件
export default [
{
path: '/homeDetail',
component: HomeDetail,
},
{
path: '/home',
component: Home
},
]
-
将1步骤中所有处理好的路由和相关配置在createStackNavigator中定义好。
-
封装一个负责跳转的类topNavigator(内部是StackActions和navigationActions跳转),对于外部而言传入参数分别为模块名字,路由,参数。
topNavigator.push(模块名, 路由名, 参数})
# demo
topNavigator.push('home', '/homeDetial', {params: params})
topNavigator.replace(__onamespace, '/add-members', {params: params})
topNavigator.back()
- 又或者是每个模块下面再创建一个文件暴露跳转方法,如下示例,这样就基本完成多个模块间的路由跳转问题。
/**
* 跳转到首页详情
*/
export default function goHomeDetail(detailOps: HomeDetaiOps) {
topNavigator.push(__onamespace, '/homeDetail', { params: detailOps });
}
# 其他模块文件跳转直接调用goHomeDetail(...)
5. url跳转
动态解析服务器下发路由也是界面跳转常用的一种方式,因此可以定义一套协议,例如:
pa://XX/home/homedetail?name='zhangsan'&age=10
。客户端做一个专门解析路由的类,将url解析模块名字为home,路由路径为homedetail,参数为name和age,再执行跳转方法。这样就能成功跳转到home模块下面的homeDetail页面,搞定!
网友评论