Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 36377|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-4-10 16:27:02 | 显示全部楼层 |阅读模式

     一、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可以获取的一些方法:

    1 navigate - 转到另一个页面, 计算出需要执行的操作  (常用) 2 goBack - 关闭活动屏幕并在堆栈中向后移动  (常用) 3 addListener - 订阅导航生命周期的更新 4 isFocused - 函数返回 true 如果屏幕焦点和 false 否则。 5 state - 当前状态/路由  (常用)
    6 setParams - 对路由的参数进行更改  (常用) 7 getParam - 获取具有回退的特定参数  (常用) 8 dispatch - 向路由发送 action  (常用) 9 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还提供如下的一些方法:

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

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

    1 openDrawer - 打开 2 closeDrawer - 关闭 3 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 方法也要随着修改,灵活一点。。。

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-30 04:08 , Processed in 0.097694 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表