博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
react-navigation的多次点击重复跳转同一页面、不在堆栈路由页面使用navigation方法的解决思路、withNavigation的使用
阅读量:4084 次
发布时间:2019-05-25

本文共 6900 字,大约阅读时间需要 23 分钟。

一、react-navigation的初使用

createStackNavigator  ==> createSwitchNavigator  ==>  createAppContainer

 

createBottomTabNavigator ==> 自定义的底部Tab

 

NavigationActions 和 StackActions 可以获取navigation的方法名

 

二、this.props.navigation使用的方法和属性

 详细请看: 

1. 应用中的每个页面组件都会自动提供 this.props.navigation

this.props.navigation可以获取的一些方法:

  • navigate - 转到另一个页面, 计算出需要执行的操作  (常用)
  • goBack - 关闭活动屏幕并在堆栈中向后移动  (常用)
  • addListener - 订阅导航生命周期的更新
  • isFocused - 函数返回 true 如果屏幕焦点和 false 否则。
  • state - 当前状态/路由  (常用)
  • setParams - 对路由的参数进行更改  (常用)
  • getParam - 获取具有回退的特定参数  (常用)
  • dispatch - 向路由发送 action  (常用)
  • dangerouslyGetParent - 返回父级 navigator 的函数

注意: this.props.navigation并不是在所有页面(组件)中都可以使用,而是必须在StackNavigator、DrawerNavigator中声明的screen组件,才可以使用this.props.navigation

也就是说,screen组件会自动获得这个props

 

this.props.navigation 上还有一些方法取决于当前 navigator 的附加函数(StackNavigator 和 DrawerNavigator)

2. 如果是StackNavigator,除了以上方法,this.props.navigation还提供如下的一些方法:

  • push - 推一个新的路由到堆栈  (常用)
  • pop - 返回堆栈中的上一个页面  (常用)
  • popToTop - 跳转到堆栈中最顶层的页面  (常用)
  • replace - 用新路由替换当前路由
  • reset- 操作会擦除整个导航状态,并将其替换为多个操作的结果。  (常用)
  • dismiss - 关闭当前堆栈

3. 如果是DrawerNavigator,除了以上方法,this.props.navigation还提供如下的一些方法:

  • openDrawer - 打开
  • closeDrawer - 关闭
  • toggleDrawer - 切换,如果是打开则关闭,反之亦然

由于笔者没有使用过DrawerNavigator,在此就不做说明;

以上内容均摘自react-navigation的官网,但是官网有点繁琐,写此以自用,有读者也是我的幸运。

 

三、react-navigation的特殊方法

===============================================================

==> 清空堆栈,跳转指定页面

复制代码

import {NavigationActions, StackActions} from 'react-navigation'const resetAction = StackAction.reset({  index: 0,  actions: [NAvigationActions.navigate({ routeName: 'HomeScreen'})],});//使用this.props.navigation.dispatch(resetaction)

复制代码

说明: 上面的方法是使用dispatch重写了reset方法,

也可以直接使用reset方法:this.props.navigation.reset()

import { NavigationActions } from 'react-navigation';navigation.reset([NavigationActions.navigate({ routeName: 'HomeScreen' })], 0)

 

========================================================================

//在不在StackNavigation的堆栈中的页面,如何使用navigation

1.在主Navigator的组件中添加ref,并导出

复制代码

//StackNavigator来自createStackNavigator方法const MainNavigator  = createAppContainer(StackNavigator);import {setTopLevelNavigator} from 'xxx.js'export default calss Navigator extends Component{    render() {        return(            
{setTopLevelNavigator(navigatorRef )}}    //setTopLevelNavigator来自需要使用的页面       /> ) }}

复制代码

说明: 将MainNavigator 通过ref 传递给 其他页面传过来的 setTopLevelNavigator

 

2.在需要使用的页面,接收这个ref引用,如xxx.js

复制代码

let  _navigator;export function setTopLevelNavigator(navigatorRef ) {  _navigator = navigatorRef }// 定义navigate 方法function navigate(routeName, params) {  _navigator && __navigator .dispatch(   NavigationActions.navigate({    type: NavigationActions.NAVIGATE,    routeName,    params  })  )}// 定义dispatch方法function dispatch(params) {  _navigator && __navigator .dispatch(     params  )}//使用,直接使用上面的方法即可dispatch(resetAction)  //resetAction同上  navigate("Home", {title: 'profile'})

复制代码

说明: 通过setTopLevelNavigator去主导航页面接收navigation相关的方法

 

另外: 使用withNavigation(Component) 可以使得组件携带navigation相关的方法

withNavigation是一个更高阶的组件,它将navigationprop 传递给一个包装组件。当你不能navigation直接将prop 传递给组件时,或者在深度嵌套的子级的情况下不想传递它时,它很有用。

withNavigation(Component) 返回一个Component。

复制代码

import React from 'react';import { Button } from 'react-native';import { withNavigation } from 'react-navigation';class MyBackButton extends React.Component {  render() {    return 

复制代码

 

========================================================================

==》阻止多次点击重复跳转同一页面

复制代码

const navigateOnce = (getStateForAction) => (action, lastState) => {  const {type, routeName, params} = action;   return (    lastState &&    (type === StackActions.PUSH) &&   //此处原先使用NavigationActions.NAVIGATE    routeName === lastState.routes[lastState.routes.length - 1].routeName &&    JSON.stringify(params) === JSON.stringify(lastState.routes[lastState.routes.length - 1].params)  ) ? null : getStateForAction(action, lastState)}//使用,MainNavigator是主导航页面通过createAppContainer方法的返回值MainNavigator.router.getStateForAction = navigateOnce(MainNavigator.router.getStateForAction)

复制代码

说明: MainNavigator经过 getStateForAction 检查校验,阻止多次点击跳转相同页面的情况发生

注意: 当你使用createSwitchNavigator时,就在路由数组外在套上一层switch数组,所以 lastState.routes[lastState.routes.length - 1] 可能取不到想要的值,因为还有一层数组

 

6月26日修改: 

当使用了createSwitchNavigator时,修改上面的 navigateOnce 方法

复制代码

const MainSwitch = createSwitchNavigator({    MainStack: MainStack,    ...    //其他})const MainNavigator = createAppContainer(MainSwitch);const navigateOnce = (getStateForAction) => (action, lastState) => {  const {type, routeName, params} = action;    //此处需要注意,使用了createSwitchNavigator后,lastState.routes[lastState.routes.length - 1]拿不到我们想要的那个对象    const mainStackRoutes = lastState && lastState.routes.find((item)=>item.key === "MainStack");    //拿到我们想要的那个对象   return (    mainStackRoutes &&    (type === StackActions.PUSH) &&   //此处原先使用NavigationActions.NAVIGATE    routeName === mainStackRoutes .routes[mainStackRoutes .routes.length - 1].routeName &&    JSON.stringify(params) === JSON.stringify(mainStackRoutes .routes[mainStackRoutes .routes.length - 1].params)  ) ? null : getStateForAction(action, lastState)}//使用,MainNavigator是主导航页面通过createAppContainer方法的返回值MainNavigator.router.getStateForAction = navigateOnce(MainNavigator.router.getStateForAction)

复制代码

 

但是,当我们使用了createSwitchNavigator时,又使用了createDrawerNavigator,于是,再次修改上面的 navigateOnce 方法

复制代码

const MainDrawer = createDrawerNavigator({    MainStack: MainStack,    ...    //其他}, {    order: ['MainStack'],    initialRouteName: 'MainStack',    ...})const MainSwitch = createSwitchNavigator({    MainDrawer : MainDrawer ,    StartPresentation: StartPresentation,    //APP启动页    ...    //其他}, {    initialRouteName: 'StartPresentation',    ...})const MainNavigator = createAppContainer(MainSwitch);const navigateOnce = (getStateForAction) => (action, lastState) => {  const {type, routeName, params} = action;    //使用了createDrawerNavigator后,上面的方法也拿不到我们想要的对象    const mainDrawerRoutes = lastState && lastState.routes.find((item)=>item.key === "MainDrawer ");    //拿到我们想要的那个对象    //此处需要注意,使用了createSwitchNavigator后,lastState.routes[lastState.routes.length - 1]拿不到我们想要的那个对象    const mainStackRoutes = mainDrawerRoutes&& mainDrawerRoutes.routes.find((item)=>item.key === "MainStack");    //拿到我们想要的那个对象         return (    mainStackRoutes &&    (type === StackActions.PUSH) &&   //此处原先使用NavigationActions.NAVIGATE    routeName === mainStackRoutes .routes[mainStackRoutes .routes.length - 1].routeName &&    JSON.stringify(params) === JSON.stringify(mainStackRoutes .routes[mainStackRoutes .routes.length - 1].params)  ) ? null : getStateForAction(action, lastState)}//使用,MainNavigator是主导航页面通过createAppContainer方法的返回值MainNavigator.router.getStateForAction = navigateOnce(MainNavigator.router.getStateForAction)

复制代码

总而言之,当我们修改navigation代码结构时,navigateOnce 方法也要随着修改,灵活一点。。。

转载地址:http://tsqni.baihongyu.com/

你可能感兴趣的文章
现在来看,做个普罗米修斯的docker镜像对我而言并不难,对PX4仿真环境配置也熟悉了。
查看>>
删除docker容器和镜像的命令
查看>>
VINS-Fusion Intel® RealSense™ Depth Camera D435i
查看>>
使用Realsense D435i运行VINS-Fusion并建图
查看>>
gazebo似乎就是在装ROS的时候一起装了,装ROS的时候选择的是ros-melodic-desktop-full的话。
查看>>
React + TypeScript 实现泛型组件
查看>>
TypeScript 完全手册
查看>>
React Native之原理浅析
查看>>
Git操作清单
查看>>
基础算法
查看>>
前端面试
查看>>
React Hooks 异步操作踩坑记
查看>>
聊聊编码那些事,顺带实现base64
查看>>
TypeScript for React (Native) 进阶
查看>>
React 和 ReactNative 的渲染机制/ ReactNative 与原生之间的通信 / 如何自定义封装原生组件/RN中的多线程
查看>>
JavaScript实现DOM树的深度优先遍历和广度优先遍历
查看>>
webpack4 中的 React 全家桶配置指南,实战!
查看>>
react 设置代理(proxy) 实现跨域请求
查看>>
通过试题理解JavaScript
查看>>
webpack的面试题总结
查看>>