react-navigation使用技巧

作者: 挂着铃铛的兔 | 来源:发表于2017-05-04 10:14 被阅读103948次

react-native.jpeg

本文是基于最新的react-navigation^1.0.0-beta.23来书写的。

如果遇到什么问题可以在评论区回复,或者加QQ群397885169讨论

因为react-navigation之前存在的问题相对较多,本文更新会稍慢,而且,我现在项目使用的是基于它封装的react-native-router-fluxV4版本,现在也推荐给大家使用。在下面的文章中,我提供了简易的Demo,react-native-router-flux提供了更多的API和方法教给用户使用,如果遇到不会的问题,欢迎加群讨论

react-native-router-flux使用技巧(API篇)

识兔,一款用来识别图片的开源项目,在未来还会添加更多有意思的东西

react-navigation的Demo

react-navigation使用技巧(进阶篇)

什么是react-navigation?

react-native从开源至今,一直存在几个无法解决的毛病,偶尔就会复发让人隐隐作痛,提醒你用的不是原生,其中包括列表的复用问题,导航跳转不流畅的问题等等。
终于facebook坐不住了,在前一段时间开始推荐使用react-navigation,并且在0.44发布的时将之前一直存在的Navigator废弃了。
react-navigation是致力于解决导航卡顿,数据传递,Tabbar和navigator布局,支持redux。虽然现在功能还不完善,但基本是可以在项目中推荐使用的。

属性

react-navigation分为三个部分。
StackNavigator类似顶部导航条,用来跳转页面和传递参数。
TabNavigator类似底部标签栏,用来区分模块。
DrawerNavigator抽屉,类似从App左侧滑出一个页面,在这里不做讲解。
下面会分开讲解官网提供的配置方法,但顺序可能会官网不一样。

screenProps

之前是没有介绍这个属性的,但经过这么久发现,很多人都不知道这个属性,不知道它能干嘛,在这里我就简单的介绍下

screenProps:react-navigation自带的一个属性,属于navigationOptions的一个属性,可以全局控制navigationOptions中的某些值,比如说你想做换肤功能,修改这个属性绝对是最简单的方式。

// 假设App就是项目中的入口文件,如果还不知道,可以看下Demo,在这里我将主题色通过screenProps属性修改成'red'
<App screenProps={{themeColor:'red'}}>

// 在页面中就可以通过screenProps来直接改变了,这个在Demo
中的Test2里面

static navigationOptions = ({navigation,screenProps}) => ({
        // 这里面的属性和App.js的navigationOptions是一样的。
                headerStyle:{backgroundColor:screenProps?
                screenProps.themeColor:
                '#4ECBFC'},


    )
})

StackNavigator 基础用法/属性介绍

const MyApp = StackNavigator({
    // 对应界面名称
    MyTab: {
        screen: MyTab,
    },
    Detail: {
        screen: Detail,
        navigationOptions:{
            headerTitle:'详情',
            headerBackTitle:null,
        }
    },
}, {
    headerMode: 'screen',
});

导航配置

screen:对应界面名称,需要填入import之后的页面。

navigationOptions:配置StackNavigator的一些属性。

  • title:标题,如果设置了这个导航栏和标签栏的title就会变成一样的,所以不推荐使用这个方法。
  • header:可以设置一些导航的属性,当然如果想隐藏顶部导航条只要将这个属性设置为null就可以了。
  • headerTitle:设置导航栏标题,推荐用这个方法。
  • headerBackTitle:设置跳转页面左侧返回箭头后面的文字,默认是上一个页面的标题。可以自定义,也可以设置为null
  • headerTruncatedBackTitle:设置当上个页面标题不符合返回箭头后的文字时,默认改成"返回"。(上个页面的标题过长,导致显示不下,所以改成了短一些的。)
  • headerRight:设置导航条右侧。可以是按钮或者其他。
  • headerLeft:设置导航条左侧。可以是按钮或者其他。
  • headerStyle:设置导航条的样式。背景色,宽高等。如果想去掉安卓导航条底部阴影可以添加elevation: 0,iOS下用shadowOpacity: 0。
  • headerTitleStyle:设置导航条文字样式。安卓上如果要设置文字居中,只要添加alignSelf:'center'就可以了。在安卓上会遇到,如果左边有返回箭头导致文字还是没有居中的问题,最简单的解决思路就是在右边也放置一个空的按钮。
在最新版本的react-navigation中,安卓居中可以使用 flex:1, textAlign: 'center'来实现。
  • headerBackTitleStyle:设置导航条返回文字样式。
  • headerTintColor:设置导航栏文字颜色。总感觉和上面重叠了。
  • headerPressColorAndroid:安卓独有的设置颜色纹理,需要安卓版本大于5.0
  • gesturesEnabled:是否支持滑动返回手势,iOS默认支持,安卓默认关闭
  • gestureResponseDistance:对象覆盖触摸从屏幕边缘开始的距离,以识别手势。 它需要以下属性:
    • horizontal - number - 水平方向的距离 默认为25。
    • vertical - number - 垂直方向的距离 默认为135。
// 设置滑动返回的距离
gestureResponseDistance:{horizontal:300},

注:beta13新出的东西,挺有意思,以后可以手动控制返回了

导航视觉效果

mode:定义跳转风格。

  • card:使用iOS和安卓默认的风格。
  • modal:iOS独有的使屏幕从底部画出。类似iOS的present效果

headerMode:边缘滑动返回上级页面时动画效果。

  • float:iOS默认的效果,可以看到一个明显的过渡动画。
  • screen:滑动过程中,整个页面都会返回。
  • none:没有动画。

cardStyle:自定义设置跳转效果。

transitionConfig: 自定义设置滑动返回的配置。
onTransitionStart:当转换动画即将开始时被调用的功能。
onTransitionEnd:当转换动画完成,将被调用的功能。

path:路由中设置的路径的覆盖映射配置。
initialRouteName:设置默认的页面组件,必须是上面已注册的页面组件。
initialRouteParams:初始路由的参数。

path:path属性适用于其他app或浏览器使用url打开本app并进入指定页面。path属性用于声明一个界面路径,例如:【/pages/Home】。此时我们可以在手机浏览器中输入:app名称://pages/Home来启动该App,并进入Home界面。

TabNavigator 基础用法/属性介绍

const MyTab = TabNavigator({
    ShiTu: {
        screen: ShiTu,
        navigationOptions:{
            tabBarLabel: '识兔',
            tabBarIcon: ({tintColor}) => (
                <Image
                    source={{uri : '识兔'}}
                    style={[tabBarIcon, {tintColor: tintColor}]}
                />
            ),
        },
    }, {
    tabBarPosition: 'bottom',
    swipeEnabled:false,
    animationEnabled:false,
    tabBarOptions: {
        style: {
            height:49
        },
        activeBackgroundColor:'white',
        activeTintColor:'#4ECBFC',
        inactiveBackgroundColor:'white',
        inactiveTintColor:'#aaa',
        showLabel:false,
    }
});

屏幕导航配置

screen:和导航的功能是一样的,对应界面名称,可以在其他页面通过这个screen传值和跳转。
navigationOptions:配置TabNavigator的一些属性

  • title:标题,会同时设置导航条和标签栏的title,还是不推荐这种方式。
  • tabBarVisible:是否隐藏标签栏。默认不隐藏(true)
  • tabBarIcon:设置标签栏的图标。需要给每个都设置。
  • tabBarLabel:设置标签栏的title。推荐这个方式。
  • tabBarOnPress:设置tabBar的点击事件,内部提供了两个属性,一个方法(obj)。
    beta13新添加的方法,使用方式有些奇葩,如果想要使用,请参照下面的代码
tabBarOnPress:(obj)=>{
            console.log(obj);

            obj.jumpToIndex(obj.scene.index)
        },

标签栏配置

tabBarPosition:设置tabbar的位置,iOS默认在底部,安卓默认在顶部。(属性值:'top','bottom')
swipeEnabled:是否允许在标签之间进行滑动。
animationEnabled:是否在更改标签时显示动画。
lazy:是否根据需要懒惰呈现标签,而不是提前制作,意思是在app打开的时候将底部标签栏全部加载,默认false,推荐改成true哦。
initialRouteName: 设置默认的页面组件
backBehavior:按 back 键是否跳转到第一个Tab(首页), none 为不跳转

tabBarOptions:配置标签栏的一些属性

iOS属性
  • activeTintColor:label和icon的前景色 活跃状态下(选中)。
  • activeBackgroundColor:label和icon的背景色 活跃状态下(选中) 。
  • inactiveTintColor:label和icon的前景色 不活跃状态下(未选中)。
  • inactiveBackgroundColor:label和icon的背景色 不活跃状态下(未选中)。
  • showLabel:是否显示label,默认开启。
  • style:tabbar的样式。
  • labelStyle:label的样式。
安卓属性
  • activeTintColor:label和icon的前景色 活跃状态下(选中) 。
  • inactiveTintColor:label和icon的前景色 不活跃状态下(未选中)。
  • showIcon:是否显示图标,默认关闭。
  • showLabel:是否显示label,默认开启。
  • style:tabbar的样式。
  • labelStyle:label的样式。
  • upperCaseLabel:是否使标签大写,默认为true。
  • pressColor:material涟漪效果的颜色(安卓版本需要大于5.0)。
  • pressOpacity:按压标签的透明度变化(安卓版本需要小于5.0)。
  • scrollEnabled:是否启用可滚动选项卡。
  • tabStyle:tab的样式。
  • indicatorStyle:标签指示器的样式对象(选项卡底部的行)。安卓底部会多出一条线,可以将height设置为0来暂时解决这个问题。
  • labelStyle:label的样式。
  • iconStyle:图标的样式。
    ps:很多人问我,为什么安卓上的tabbar文字会下移, 是因为安卓比iOS多了一个属性,就是iconStyle,通过设置labelStyleiconStyle两个样式,外加style的高度,来使效果更佳合理.

跳转

navigate('Detail',{
                   title:'图片详情',
                   url:item.url,
                   });

Detail:在StackNavigator中注册的页面,需要一一对应,才能跳转到相应的页面
title:在跳转的页面可以通过this.props.navigation.state.params.title获取到这个参数。当然这个参数可以随便填写,都可以通过this.props.navigation.state.params.xxx获取。

回调传参

navigate('Detail',{
                   // 跳转的时候携带一个参数去下个页面
                   callback: (data)=>{
                         console.log(data); // 打印值为:'回调参数'
                     }
                   });
const {navigate,goBack,state} = this.props.navigation;
// 在第二个页面,在goBack之前,将上个页面的方法取到,并回传参数,这样回传的参数会重走render方法
state.params.callback('回调参数');
goBack();

自定义

项目中基本是没可能用自带的那个导航条的,自带导航条左侧的按钮永远是蓝色的,如果我们需要更改按钮颜色,就需要用到自定义的功能了。

const StackOptions = ({navigation}) => {
    console.log(navigation);
    let {state,goBack} = navigation;
    
    // 用来判断是否隐藏或显示header
    const visible= state.params.isVisible;
    let header;
    if (visible === true){
        header = null;
    }
    const headerStyle = {backgroundColor:'#4ECBFC'};
    const headerTitle = state.params.title;
    const headerTitleStyle = {fontSize:FONT_SIZE(20),color:'white',fontWeight:'500'}
    const headerBackTitle = false;
    const headerLeft = (
        <Button
            isCustom={true}
            customView={
                            <Icon
                                name='ios-arrow-back'
                                size={30}
                                color='white'
                                style={{marginLeft:13}}
                            />
                        }
            onPress={()=>{goBack()}}
        />
    );
    return {headerStyle,headerTitle,headerTitleStyle,headerBackTitle,headerLeft,header}
};

然后通过下面的方法调用就可以自定制导航了。

const MyApp = StackNavigator({
    MyTab: {
        screen: MyTab,
    },
    Detail: {
        screen: Detail,
        navigationOptions: ({navigation}) => StackOptions({navigation})
    },
)};

在页面中使用的时候,在跳转页面的时候需要传递title参数,才能看到效果哦。

自定义tabbar

早上有人问我,tabbar的图标可不可以使用原图,选中状态下可不可以设置其他图标。研究了一下官方文档,发现tabBarIcon除了tintColor还有另一个属性,用来判断选中状态的focused

 tabBarIcon: ({tintColor,focused}) => (
                focused
                    ?
                    <Image
                        source={{uri : '识兔'}}
                        style={tabBarIcon}
                    />
                    :
                    <Image
                        source={{uri : '干货'}}
                        style={[tabBarIcon, {tintColor: tintColor}]}
                    />
            ),

通过判断focused,选中状态下使用识兔图标,未选中状态使用干货图标。
如果想使用图标原来的样子,那就将styletintColor去掉,这样就会显示图标原本的颜色。

再封装

export const TabOptions = (tabBarTitle,normalImage,selectedImage,navTitle) => {
    // console.log(navigation);
    const tabBarLabel = tabBarTitle;
    console.log(navTitle);
    const tabBarIcon = (({tintColor,focused})=> {
        return(
            focused
                ?
                <Image
                    source={{uri : normalImage}}
                    style={[TabBarIcon, {tintColor: tintColor}]}
                />
                :
                <Image
                    source={{uri : selectedImage}}
                    style={[TabBarIcon, {tintColor: tintColor}]}
                />
        )
    });
    const headerTitle = navTitle;
    const headerTitleStyle = {fontSize:FONT_SIZE(20),color:'white'};
    // header的style
    const headerStyle = {backgroundColor:'#4ECBFC'};
    return {tabBarLabel,tabBarIcon,headerTitle,headerTitleStyle,headerStyle};
};

在static中使用this方法

我之前文章中是将navaigationOptions的方法写在了app.js中,没有在页面中通过static navaigationOptions来初始化页面,这段时间刚好有人问,所以在这里就写一下该怎么弄。

首先需要在componentDidMount(){}中动态的添加点击事件
属性给params
componentDidMount(){

    this.props.navigation.setParams({
        title:'自定义Header',
        navigatePress:this.navigatePress
    })
}
navigatePress = () => {
    alert('点击headerRight');
    console.log(this.props.navigation);
}
接下来就可以通过params方法来获取点击事件了
static navigationOptions = ({ navigation, screenProps }) => ({
        title: navigation.state.params?navigation.state.params.title:null,
        headerRight:(
            <Text onPress={navigation.state.params?navigation.state.params.navigatePress:null}>
                返回
            </Text>
        )
});

让安卓实现push动画

之前我群里的讨论怎么让安卓实现类似iOS的push动画,后来翻看官方issues的时候,真的发现了实现push动画的代码,在这里共享下

// 先引入这个方法
import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';

// 在StackNavigator配置headerMode的地方,使用transitionConfig添加
{
    headerMode: 'screen',
    transitionConfig:()=>({
        screenInterpolator:CardStackStyleInterpolator.forHorizontal,
    })
}

关于goBack返回指定页面

react-navigation是提供了goBack()到指定页面的方法的,那就是在goBack()中添加一个参数,但当你使用goBack('Main')的时候,你会发现并没有跳转,原因是react-navigation默认goBack()中的参数是系统随机分配的key,而不是手动设置的routeName,而方法内部又没有提供可以获得key的方法,所以这里只能通过修改源码将key换成routeName了。
下面的内容直接引用了hello老文的内容

把项目/node_modules/react-navigation/src/routers/StackRouter.js文件里的 
const backRoute = state.routes.find((route: *) => route.key === action.key); 
改成 const backRoute = state.routes.find(route => route.routeName === action.key);

但不是很完美, 这里的component要填想返回的组件的前一个组件的routeName, 比如你的栈里顺序是home1, home2, home3, home4, 在home4里要返回home2, 使用this.props.navigation.goBack('home3');; 并且又会带出一个问题: goBack()方法没反应了, 必须加个null进去, 写成goBack(null)...

关于goBack返回指定页面的修改完善版

if (action.type === NavigationActions.BACK) {
    let backRouteIndex = null;
    if (action.key) {

      const backRoute = state.routes.find(
        /* $FlowFixMe */
        /* 修改源码 */
        route => route.routeName === action.key
        /* (route: *) => route.key === action.key */
      );
      /* $FlowFixMe */
      console.log('backRoute =====',backRoute);
      backRouteIndex = state.routes.indexOf(backRoute);
      console.log('backRoute =====',backRouteIndex);
    }
    if (backRouteIndex == null) {
      return StateUtils.pop(state);
    }
    if (backRouteIndex >= 0) {
      return {
        ...state,
        routes: state.routes.slice(0, backRouteIndex+1),
        index: backRouteIndex - 1 + 1,
      };
    }
  }

感谢群友conan的贡献,将源码改成上面的样子,就可以使用goBack()返回指定页面了,这样的优点不言而喻,但缺点就是每次调用goBack(),如果只是简单的返回上一页需要加上null参数,类似这样goBack(null)

如果这样修改,在滑动返回的时候,会有很大几率让项目卡死,请注意使用该方法,推荐集成redux。

关于快速点击会导致多次跳转的问题解决办法

感谢群友编程大叔的贡献,如果想解决快速点击跳转的问题,需要修改部分源码。

修改react-navigation目录下,scr文件夹中的addNavigationHelpers.js文件,可以直接替换成下面的文本,也可以查看原版链接

 export default function<S: *>(navigation: NavigationProp<S, NavigationAction>) {
  // 添加点击判断
  let debounce = true;
  return {
      ...navigation,
      goBack: (key?: ?string): boolean =>
          navigation.dispatch(
              NavigationActions.back({
                  key: key === undefined ? navigation.state.key : key,
              }),
          ),
      navigate: (routeName: string,
                 params?: NavigationParams,
                 action?: NavigationAction,): boolean => {
          if (debounce) {
              debounce = false;
              navigation.dispatch(
                  NavigationActions.navigate({
                      routeName,
                      params,
                      action,
                  }),
              );
              setTimeout(
                  () => {
                      debounce = true;
                  },
              500,
              );
              return true;
          }
          return false;
      },
    /**
     * For updating current route params. For example the nav bar title and
     * buttons are based on the route params.
     * This means `setParams` can be used to update nav bar for example.
     */
    setParams: (params: NavigationParams): boolean =>
      navigation.dispatch(
        NavigationActions.setParams({
          params,
          key: navigation.state.key,
        }),
      ),
  };
}

安卓上,使用TextInput的时候会让TabBar顶起来的解决办法

最简单的解决办法就是在android目录中,添加一句话

目录:android/app/src/main/AndroidManifest.xml中,添加

 android:windowSoftInputMode="stateAlwaysHidden|adjustPan|adjustResize"

ps:在iOS下如果想一劳永逸的解决键盘问题,请使用IQKeyBoardManager

总结

react-navigation才开始用的时候感觉是复杂的,但用的多了,会感觉真的很不错。
如果在文章中有什么不懂的问题,欢迎在评论区评论,也可以发私信,加QQ群397885169一起讨论哦

相关文章

网友评论

  • 八戒莫慌:您好,shitu在npm install的时候报以下错误:
    [server error] Cannot load the stats for react-native-masonry – please try again later

    Thanks for installing react-native-masonry 🙏
    Please consider donating to our open collective
    to help us maintain this package.

    👉 Donate: https://opencollective.com/react-native-masonry/donate

    npm WARN react-native-masonry@0.5.0-alpha.1 requires a peer of react-native@^0.43.0 but none is installed. You must install peer dependencies yourself.
    请问该如何解决呢?!
    挂着铃铛的兔:@八戒莫慌 使用yarn试一试。 如果再不行,可以把这个库删掉。这个库没有用到
  • 不羁的躁动:你好,我的为什么每次点击tababar的选项,都会报警告 'Method `jumpToIndex` is deprecated. Please upgrade your code to use `jumpTo` instead.', 'Change your code from `jumpToIndex(2)` to `jumpTo(\'Mine\').`' ,求解答
    九龙:创建Tabbar的时候不能用TabNavigator需要用createBottomTabNavigator
    挂着铃铛的兔:@風花丶雪楽 这个是新版本没有这个方法了。重写就可以了。
    風花丶雪楽:请问这个问题解决了么
  • zhouwude:代码怎么做到只能提示呢,感觉重载导航样式 只能手写。不知道有没有方式可以做到。
  • 938b56c2c746:在static中使用this方法,如何在navigationOptions中使用的是TextInput方法调用onChange事件,怎么往出传值?
  • 5ec1da87f063:能更新下2.0吗?
  • 静侯花开:楼主,现在有个需要记录路由跳转次数的需求。能否咨询下有没有比较好的解决办法,只想到addListener这种法子了
  • Mr_panmin:请问楼主如何自定义indicatorStyle,我想做一个向下开口的箭头的样式
  • 06290933e539:可以使用react-navigation做一个中间有一个加号图标的底部tab吗
  • 8c08e527f27a:StackNavigator is not defined 我按照你写的 一步一步来
    StackNavigator 没有定义 好乱
  • 果果_d467:想问个问题,关于自定义Push动画,mode这个属性,不同的界面可以不同定制吗,现在改完都是统一换成一个动画了。
  • 724ca850e8b1:很详细,感谢作者
  • 70c435b7dc8d:我有ABC三个界面 从第三个界面C返回到第一个界面A 会先返回B然后再返回A导致动画会跳转两次?reset的时候也会好像。以及有没有办法通过代码切换Tab的界面呢?具我了解应该是JumpToIndex这个方法 可是不知道怎么调用 都是undefined
    fangcaiwen:解决了嘛?我解决了这个问题
  • layneshi:大佬,设置tabBarOptions tababar背景色,android变了,为什么ios没有变?
  • xnllc:当前新版本(1.0.0-beta.27)里面 CardStackStyleInterpolator 已经改了路径
    import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator';
  • _海角_:通常是点击Tabbar 进行切换,如果像不点击Tabbar 切换Tab,请问如何实现
  • 以德扶人:对于点击多次跳转的问题,我这边也是用拦截的方式,不过方法比较简单,也不需要改源码,只要2段代码即可,大概代码是这样:
    ```
    const SimpleApp = StackNavigator({
    Home: { screen: HomeScreen },
    });

    //主要是这一步
    const navigateOnce = (getStateForAction) => (action, state) => {
    const {type, routeName} = action;
    return (
    state &&
    type === NavigationActions.NAVIGATE &&
    routeName === state.routes[state.routes.length - 1].routeName
    ) ? null : getStateForAction(action, state);
    };

    //这是第二步
    SimpleApp.router.getStateForAction = navigateOnce(SimpleApp.router.getStateForAction);

    ```

    完整的写在我文章里了https://www.jianshu.com/p/14d482f97835
  • 街角仰望:你好 请问你遇到过把header设置成null隐藏导航栏的时候切换下面tab页面,页面会来回跳转的问题么?RN版本为0.50.0
    街角仰望:@挂着铃铛的兔 是screen 模式
    挂着铃铛的兔:@街角仰望 用screen模式
  • 4cb4fcf1db9d:改成这样就不用goBack(null)这么麻烦了...
    if (backRouteIndex < 0 || backRouteIndex == null) {
    return StateUtils.pop(state);
    }
  • We_Me:一级棒
  • 梁同桌:写的真 给力。。。。
  • cfb9a19376a8:楼主按照你的方法,修改源码goBack()和返回指定页面仍然不能用,我的版本是0.50.3
  • 啸雨:如何在 DrawerNavigator 里面进行页面跳转呢?
  • f86fb9a8ce6a:如果把页面集成到Tab然后把tab放入导航,那如果另一个页面自定义的返回按钮怎么样可以返回到tab页面的第二个页面,NavigationActions.navigate({ routeName: 'Test2'}) , 页面是集成在tab中放入导航中的,其实导航中并没有这个页面,返回tab页面的第二个页面是defined
    f86fb9a8ce6a:@挂着铃铛的兔 谢谢,
    f86fb9a8ce6a:@挂着铃铛的兔 好的,谢谢,请问有IOS实机测试时,有没有碰到过 导航栏 返回按钮要按很多次才会返回的情况,我因为这个问题把所有的返回按钮都换成了自定义的,没测试还不知道有没有效果,而且就碰到了我说的tab返回的问题
    挂着铃铛的兔:暂时的解决办法是。先reset再navigate
  • 还没想到叫什么:导航的mode怎么使用呢
    挂着铃铛的兔:Model效果?
  • b3015781d7e6:lz,TabNavigator 的每个路由页面的导航栏设置和stackNavigator的不一样吗?我从stackNavigator跳转到TabNavigator ,然后tab的导航栏不能直接设置,有解决方案么
    挂着铃铛的兔:不懂 加群问
  • c5b3addc3e86:文中阻止多次点击多次跳转的方法在react navigation@1.0.0-beta.11 版本中无效吗
  • adi888:我有一个向前返回N层, 或返回到指定页面的解决方案, 可以参考下

    在app.js时装载时用addNavigationHelpers生成naviagtion时,将naviagtion保存成全局变量.
    我是存在Contents中

    然后返回n层就可以这么定将
    /**
    * 返回到第N层页面, 当前页面
    * @param index
    */
    goBack(index) {
    let navigation = Contents.navigation();
    let {routes} = navigation.state;

    let idx = routes.length - index;
    if (idx < 0) {
    idx = 0;
    }

    navigation.goBack(routes[idx].key)
    }

    返回到指定页面
    /**
    * 返回到某个页面
    * @param page
    */
    goBackPage(page) {
    let navigation = Contents.navigation();
    let {routes} = navigation.state;

    let route = routes.find(item => item.routeName === page);

    let index = routes.indexOf(route);

    navigation.goBack(routes[index + 1].key)
    }
    1bd2d1f394ce:请问有示例代码吗?
  • 成为_5995:兔神,你好,如何给tabBar条的背景添加图片啊
  • 56cfe8238185:我想问一下,react navigation 可以设置 tabBar选中和未选中状态 的图标吗,像小程序那样的
    挂着铃铛的兔: @心痛說隨便你 可以。。看一下Demo里面有的
  • JeffWei:我想问下,webstorm怎么才能让这个框架能智能提示
    挂着铃铛的兔: @JeffWei 群号在上面。。。我没有看明你的问题。。
    JeffWei:@挂着铃铛的兔 该试过的都试了,可能我问的比较简单,确切点说是JavaScript的library下载了react-navigation的definitelyTyed,但是还是没有具体的智能提示.请问群多少,谢谢
    挂着铃铛的兔:@JeffWei 百百度,实在不行,加群问我
  • zach羊:您好,请教个问题:
    我在做的demo跳转逻辑是这样的:stackNavigator路由中配置的主界面中使用tabNavigator,tab中有三个界面,三个界面有自己不同的title,但是导航栏上只有tab页面的title,无法动态改变,求助
    挂着铃铛的兔: @zach羊 setparams也不行?
  • f86fb9a8ce6a:请问tab之间的切换时不刷新页面的吗?如果2个tabbar 里面的 list数据是对应的,比如 一个是 货物list, 一个是 上架货物的list , 在一个list里面点击了某件货物上架, 那应该在 上架货物list里面多一件,但发现tab之间的切换不会刷新重读页面 ,如何解决
    挂着铃铛的兔:@阿苤 进阶篇文章
    f86fb9a8ce6a:@挂着铃铛的兔 如何在tab上加点击事件? 有例子吗?
    挂着铃铛的兔: @阿苤 给tab加点击事件 或者redux
  • 谦谦君子修罗刀:如果有效果图会更棒
  • 迷迭象:在APP首页,导航条随着ScrollView的滑动而渐变,用StackNavigation怎么实现?在onScroll()方法中怎么更新导航条的状态?
    挂着铃铛的兔:@迷迭象 加群。
    迷迭象:我就是自定义的view。。但是我还是想知道怎么用StackNavigation的导航条实现,刚学RN几天,不要介意哈
    挂着铃铛的兔:隐藏自带的导航自己画一个放上去
  • f86fb9a8ce6a:问个基础问题,有home,list,update,三个页面, home到list ,list里面某条记录点击到update页面,完成update操作之后回到list页面, 我的问题是,update回到 list页面是用goback()吗?
    还是 navigate('list') ? 如果用 navigate('list');的话list 页面 的返回按钮就会回到 update页面,
    如果用goback(),那怎么刷新就list页面并且更新list页面的数据?
    f86fb9a8ce6a:@挂着铃铛的兔 但如果我是在页面的 static navigationOptions 添加了一个 headerRight 的新建按钮,这个新建按钮里有一个callback 回调函数, 但因为这个事在static里,所以回调回来 任何都得不到 , this.props,this.state, 都不能获取,也不能setState了怎么办?
    f86fb9a8ce6a:@挂着铃铛的兔 好的谢谢,好像你文章里有说到。。。
    挂着铃铛的兔:回调刷新呀。。。用goBack就行
  • 木中木:兄弟,我想问你下tabNavigator,现在是我们能够通过点击页面tab进行切换,有没有可以通过方法调用切换组件
    挂着铃铛的兔:navigate。
  • HJXu:"none:没有动画。" 这里应该是隐藏导航栏
    挂着铃铛的兔:嗯,谢啦
  • 5e64f6d1fc21:你的navigation static中this使用,,上面的代码有写问题,,this指向有问题,,
    挂着铃铛的兔:还有问题? 在外面加一层判断, 如果还不行 加群讨论咯
  • 5e64f6d1fc21:兔兔,抱抱~
  • uuuuuuw:goback的回调使用 没看见列子 博主
    挂着铃铛的兔:加群问我吧。
    挂着铃铛的兔:@独立团李李云龙 文章中有啊。。。。
  • f2087a008012:我的配置是根据你shitu项目,
    在app.js预先配置了A页面的导航栏标题,
    然后我想在A面的static navigationOptions配置覆盖app.js的配置,
    但是static navigationOptions并不能覆盖app.js的配置。
  • MeetTheBest:你好, 关于安卓上,使用TextInput的时候会让TabBar顶起来的解决办法, 想请问你一下,那句话应该写在什么位置, 望答复, 谢谢
    挂着铃铛的兔:@MeetTheBest 路径我给了啊。。。。你可以对比着放一下就行了。。实在不行,看识兔里面就有
  • f2087a008012:感谢作者让我少踩坑:smile:
  • f2087a008012:怎样让页面透过导航条?
    我想设置导航条半透明,可以看到页面的图片。
    挂着铃铛的兔:@Lbbb 自带的很难实现,推荐就是隐藏自带的,自己画一个上去
  • f86fb9a8ce6a:App.js 这不是个页面吗? 作用是什么 , 最后 export default MyNav; 就可以了吗??我是新手,以为都要
    export default class MyNav extends Component;
    f86fb9a8ce6a:@挂着铃铛的兔 谢谢
    挂着铃铛的兔:你可以认为App.js就是一个配置路由就好。
  • f86fb9a8ce6a:非常好的教程,还有Demo ,看再多官方教程不如看一个Demo
  • 街角仰望:你好,请问部分界面是从底部弹出,其他界面是默认弹出要怎么设置?
    街角仰望:@挂着铃铛的兔 好的 谢谢!
    挂着铃铛的兔:@街角仰望 暂时没有办法,只能通过拆分stack
  • 羽纱:你好,对于goback指定routeName,以及stackNavigator防止重复跳转,我有不同的看法,还望指教,谢谢。

    我不是很赞同修改源码来实现自己的功能,除非迫不得已,react-navigation官方提供了对路由拦截的方法,在https://reactnavigation.org/docs/routers/#Customizing-Routers中有描述。
    因此我觉得通过拦截来自定义路由行为是可行的。
    指定routeName来goBack和防止重复navigate的代码如下:
    ```
    function routeIsInCurrentState(state: Object, routeName: string) {
    if(state && state.routeName === routeName) {
    return true
    }

    if(state && state.routes) {
    return routeIsInCurrentState(state.routes[state.index], routeName)
    }

    return false
    }

    const defaultGetStateForAction = MyApp.router.getStateForAction;
    MyApp.router.getStateForAction = (action, state) => {
    if (state && action.type === NavigationActions.Back && action.routeName) {
    //这里可以自己在外部自定义一个ActionType,然后判断是否是自定义的ActionType
    const backRoute = state.routes.find((route: *) => route.routeName === action.routeName);
    if (backRoute) {
    const backRouteIndex = state.routes.indexOf(backRoute);
    const route = {
    ...state,
    routes: state.routes.slice(0, backRouteIndex + 1),
    index: backRouteIndex,
    };
    return route
    }
    }
    if (state && action.type === NavigationActions.Navigate) {
    if(routeIsInCurrentState(state, action.routeName)) {
    //避免重复跳转
    return state
    }
    }
    return defaultGetStateForAction(action, state)
    };
    ```

    如果react-navigation配合redux使用,那么在reducer里面就可以直接拦截action,做如上自定义操作了。

    还望指教,谢谢。
    add8a472d3cb:亲测可用,感谢 另外NavigationActions.Navigate 现在是NavigationActions.NAVIGATE
    程画:加个拦截器,重复点击跳转就解决了,另外 tabBar 切换 按钮,我完全自定义了,都不用他自带的属性,哈哈,拒绝修改源码
    Cooliean:不知道能否给一个完整点的例子呢,我吧你这个代码放我项目里面,报错了。说index不可读取undefined

    我对你这个方法比较感兴趣,谢谢了。我看了官方的没有看懂。哈哈
  • Syanbo:安卓与iOS保持统一改一个参数就行
    import TabBarBottom from 'react-navigation/src/views/TabView/TabBarBottom';
    TabNavigator ===》加
    tabBarComponent: TabBarBottom
  • 壹点微尘:安卓上的tabbar文字会下移,底部会多出一条线,可通过设置tabBarComponent:TabBarBottom解决
    Senvid丶:有效
  • kala888:报了个bug,求关心https://github.com/RabbitDream/ReactNavigationDemo/issues/1
    挂着铃铛的兔:收到,我晚上回去改好
  • CholMay:A页面跳转B页面,返回之后需要B往A传值,怎么传?
    挂着铃铛的兔:@夜晚看日出 回调。。。文章中有
  • Mars飘殇:你好,我想问个问题:顶部的navigation下面那条线怎么隐藏?用你说的elevation: 0,设置了去不掉
    Mars飘殇:@挂着铃铛的兔 现在又遇到个问题,默认的statusBar是黑色的,想变成白色,该怎么写
    挂着铃铛的兔:@Mars飘殇 :+1:🏻我忘记添加了
    Mars飘殇:自己回答吧,方法找到了,iOS下隐藏navigation底部线条用shadowOpacity: 0,安卓上用elevation: 0,放到headerStyle里面即可
  • 谈Xx:想请教下 如果我原有应用嵌入reactnative的页面,根据文档使用RCTRootView进行push,但是问题来了, 我的页面内部也有自己的导航栏处理跳转, 这个怎么办呢
  • 陌上北辰: 可以放个demo 么
    挂着铃铛的兔:@陌上北辰 加群可以看看原版。
  • 66cb6b7edca0:你好 翻译的很棒!请问 tab切换的时候,有什么好方法把旧的页面卸载掉吗?就是能让切换前的页面执行componentWillUnmount()方法
    Skyling:你现在解决了吗
    挂着铃铛的兔:@xxx2017 加群讨论吧
  • 3265e90f9ba7:headerTitleStyle:安卓上如果要设置文字居中,只要添加alignSelf:'center'。如果header有headerRight或headerLeft,headerTitle只是在header剩余部分居中,不是在header居中,请问该怎么解决?
    挂着铃铛的兔:@tomyzhou 谢谢
    72a28013dc15:好文章,收藏
    挂着铃铛的兔:@zeuscoder 最简单的解决办法。右边也加个空按钮。。。
  • dab32aad0471:楼主你好,请问StackNavigator如何实现二级也买再跳转到三级页面?
    挂着铃铛的兔:@cherryui 谢谢
    a246a7f9950b:很棒的教程
    挂着铃铛的兔:加群讨论。
  • nimw:请教一个问题,外层是一个StackNavigator, StackNavigator里有一个 TabNavigator和组件2, TabNavigator里有a,b,c,d四个tab。从组件2执行navigate进入 TabNavigator,然后点击tab-d跳转到d。 在d页面执行goBack()会返回到a。请问有办法从d直接返回到组件2吗?
    还是丹丹:@爱哭的笨小孩 开心么哈哈:clap:
    爱哭的笨小孩:@还是丹丹 我靠 找你这句backBehavior:{} 找了一个下午
    非常感谢
    还是丹丹:定义TabNavigator时,添加backBehavior:{}
  • 耳_总:楼主TabNavigator的导航在Android中总是在顶部,tabBarPosition='bottom'不起作用,设置tabBarComponent:TabBarBottom,也还是没用,不知道你有尝试过吗?这个问题怎么解决
    挂着铃铛的兔:@耳_总 加群吧,咱们讨论一下
    耳_总:@挂着铃铛的兔 模拟器
    挂着铃铛的兔:@耳_总 测试机,还是模拟器,我这边没有这个问题
  • 064455a570e4:帮兔神记录:安卓比iOS多了一个属性 叫做iconStyle ;
    安卓的tabbar上的图片, 库里面给了一个不太高的高度, 所以需要手动重定制;
    如果感觉文字向下了. 设置一下lableStyle就好了;
    兔神原话
  • 张大娃创业笔记:我想问一下,为何我用react navigation做的tabbar然后首页里面使用react-native-scrollview-tab却不能显示对应的页面呢,又没报错还可以滑动,就是不显示页面内容,只有打开一个新页面返回后才能显示,所以我想请教一下大师知道怎么解决吗?
    张大娃创业笔记: @孤影追忆 你用过底部tabbar首页的页面中再使用tabbar吗
    挂着铃铛的兔:@孤影追忆 不是很懂你的操作逻辑是什么。。。我开源的识兔项目中,也用到了你说的那个库,没看到问题。
  • 5ec1da87f063:该react-navigation可以直接用吧,不加redux那种.还有这个用于上线项目是不是坑太多了.
    挂着铃铛的兔:@5ec1da87f063 App.js已经是代码了. 可以直接复制粘贴.然后创建几个页面就好了
    5ec1da87f063:@挂着铃铛的兔 有基本的演示demo吗?没怎么看懂.
    挂着铃铛的兔:@5ec1da87f063 正常使用是够的,跳转,传值,回调。经常用的也就这些。
  • Sleet:请问一下当把一个 stack navigation嵌套在一个 drawer navigation.从drawer navigation 选择再次进入 stack navigation的时候。 stack navigation就会增加一个新的router ,如果想得到原来的router怎么办呢。是不是需要用 getScreen懒加载呀

本文标题:react-navigation使用技巧

本文链接:https://www.haomeiwen.com/subject/qsertxtx.html