一、react-navigation的初使用

createStackNavigator  ==> createSwitchNavigator  ==>  createAppContainer

createBottomTabNavigator ==> 自定义的底部Tab

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

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

详细请看: react-navigation 3.x版本的push、navigate、goback、pop、dispatch等常用方法

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

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

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

navigation的方法

注意: 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 - 关闭当前堆栈

StackNavigator的方法

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

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

DrawerNavigator的方法

由于笔者没有使用过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(
<MainNavigator
   ref={navigatorRef => {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 <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />; //此处可以使用navigation相关方法
}
}
// withNavigation returns a component that wraps MyBackButton and passes in the
// navigation prop
export default withNavigation(MyBackButton);

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

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

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 方法也要随着修改,灵活一点。。。

react-navigation的多次点击重复跳转同一页面、不在堆栈路由页面使用navigation方法的解决思路的更多相关文章

  1. 利用 runtime,解决多次点击相同 button,导致重复跳转的问题-b

    当app有点卡的时候,多次点击相同的button,经常出现,跳转了N次相同的界面(比如闲鱼) 解决办法 用运行时和分类,替换 UIControl 响应事件,根据响应的间隔时间来判断是否执行事件. 详细 ...

  2. 使用Android点击按钮跳转页面

    1.首先新建一个Android工程,命名为MyApp(名字可以自己随意起); 2.以原有的MainActivity.java文件为登录界面,然后在src文件中的包上面右击选择New目录下的Other中 ...

  3. 如何绑定android点击事件--跳转到另一个页面并实现关闭功能?

    一.点击按钮跳转到另一个页面. eg:实现从一个页面点击跳转到另一个页面 1.首先在一个布局文件(.XML)中绘画了一个跳转按钮(id为btn1): <Button         androi ...

  4. window.location.href问题,点击,跳转到首页

    onClick="window.location.href='./';" 点击,跳转到首页. location.href=url Js中实现跳转 window.location.h ...

  5. 安卓入门——————简单记账本的开发(二)-点击listview跳转并实现数据的更新

    前言:   这个博客主要实现listview的跳转并实现对数据库内容的更新并显示到listview上,还没有实现listview的实时更新和listview具体线条的添加(接下来的几篇博客会实现),如 ...

  6. mui中confirm在苹果出现bug,confirm点击确定跳转页面再返回后,页面被遮罩盖住无法使用

    项目中使用confirm mui.confirm('您还未抽奖,现在去抽奖吗?', function (res) { if (res.index === 1) { window.location.hr ...

  7. a标签点击不跳转的几种方法

    a标签点击不跳转的几种方法 1.onclick事件中返回false <a href="http://www.baidu.com" onclick="return f ...

  8. div加链接 html给div加超链接实现点击div跳转的方法[申明:来源于网络]

    div加链接 html给div加超链接实现点击div跳转的方法[申明:来源于网络] 地址:http://www.cdxwcx.com/faq/htmldivLink.html

  9. <a>标签点击不跳转

    HTML中的<a></a>标签点击不跳转的方法 一.<a href="####" ></a> 使用这个方法我们会发现<a hr ...

随机推荐

  1. 201621123005《Java程序设计》第十二次作业

    <Java程序设计>第十二次作业 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造 ...

  2. New Concept English Two 7

    $课文14 你会讲英语吗? 133. I had an amusing experience last year. 去年我有过一次有趣的经历. 134. After I had left a smal ...

  3. timer Compliant Controller project (1)--Product introduction meeting

    Last week ,I lead the meeting for new project. i'm  very excited. The meeting is divided into the fo ...

  4. .net core microservices 架构之 分布式

    .net core microservices 架构之 分布式  一:简介   自动计算都是常驻内存的,没有人机交互.我们经常用到的就是console job和sql job了.sqljob有自己的宿 ...

  5. 理解JAVA虚拟机(上)

    2016-04-16 23:10:50 在这里,我们进一步认识JAVA及JAVA虚拟机,包括它的体系结构和垃圾回收机制等,并通过虚拟机监控工具进行简单的性能调优. 一. JVM相关概念        ...

  6. pthread中互斥量,锁和条件变量

    互斥量 #include <pthread.h> pthread_mutex_t mutex=PTHREAD_MUTEX_INTIIALIZER; int pthread_mutex_in ...

  7. box2d试用

    下载之后,修改里面的Testbed,加入一个footest,测试一下俺的冰箱能不能放到厨房里面

  8. bzoj2660最多的方案

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2660 当然可以看出  选了第 i 个斐波那契数<=>选了第 i - 1 和第 i ...

  9. 关于hashmap的排序

    刚学java不久 之前在学习hashmap的时候 无意间发现,诶?怎么结果是排序的,然后重新输入了好多次,握草,原来java 1.8都实现了hashmap的排序 天真的我没有去网上查,没有去想java ...

  10. C# 播放器, 收藏

    C#写了一个调用libvlc api实现的万能视频播放器 http://www.cnblogs.com/haibindev/archive/2011/12/21/2296173.html 引用库 ht ...