iOS DeveloperReact Native高手进阶React Native开发小白

从navigator到react-navigation进阶教程

2018-05-15  本文已影响198人  CrazyCodeBoy

随着react-navigation逐渐稳定,Navigator也被光荣的退休了。在React Native生态环境中需要一款可扩展且易于使用的导航组件,Navigator 自然胜任不了,这时React Native社区便孕育出了一个开源导航组件react-navigation

react-navigation的出现替代了Navigator、 Ex-Navigation等老一代的导航组件,react-navigation可以说是Navigator的加强版,不仅有Navigator的全部功能,另外还支持底部导航类似于与iOS中的UITabBarController,此外它也支持侧拉效果方式的导航类似于Android中的抽屉效果。

这篇文章将向大家分享react-navigation的一些实用技巧,以及从navigator到react-navigation的一些实战经验。另外大家也可以学习与本教程配套的视频版:《全新导航器react-navigation精讲》

什么是导航器?

导航器也可以看成一个是普通的React组件,你可以通过导航器来定义你的App的导航结构。 导航器还可以渲染通用元素,例如可以配置的标题栏和选项卡栏。

在react-navigation中有以下三种类型的导航器:

react-navigation

{:height="90%" width="90%"}

你可以通过以上三种导航器来创建你APP,可以是其中一个也可以多个组合,这个可以根据具体的应用场景并结合每一个导航器的特性进行选择。

在开始学习三种导航器之前,我们需要先了解两个和导航关于概念:

导航器所支持的Props

const SomeNav = StackNavigator/TabNavigator/DrawerNavigator({
  // config
});

<SomeNav
  screenProps={xxx}
  ref={nav => { navigation = nav; }}
  onNavigationStateChange=(prevState, newState, action)=>{
    
  }
/>

@全新导航器react-navigation精讲

Screen Navigation Prop(屏幕的navigation Prop)

当导航器中的屏幕被打开时,它会收到一个navigation prop,navigation prop是整个导航环节的关键一员,接下来就详细讲解一下navigation的作用。

navigation包含一下功能:

注意:一个navigation有可能没有navigate、setParams以及goBack,只有state与dispatch,所以在使用navigate时要进行判断,如果没有navigate可以使用navigation去dispatch一个新的action。如:

const {navigation,theme,selectedTab}=this.props;
const resetAction = NavigationActions.reset({
    index: 0,
    actions: [
        NavigationActions.navigate({
            routeName: 'HomePage',
            params:{
                theme:theme,
                selectedTab:selectedTab
            },
        })
    ]
})
navigation.dispatch(resetAction)

@全新导航器react-navigation精讲

使用navigate进行界面之间的跳转

export const AppStackNavigator = StackNavigator({
    HomeScreen: {
        screen: HomeScreen
    },
    Page1: {
        screen: Page1
    })

class HomeScreen extends React.Component {
  render() {
    const {navigate} = this.props.navigation;

    return (
      <View>
        <Text>This is HomeScreen</Text>
        <Button
          onPress={() => navigate('Page1', {name: 'Devio'})}
          title="Go to Page1"
        />
      </View>
     )
   }
}

@全新导航器react-navigation精讲

使用state的params

可以通过this.props.state.params来获取通过setParams(),或navigation.navigate()传递的参数。

<Button
    title={params.mode === 'edit' ? '保存' : '编辑'}
    onPress={() =>
        setParams({mode: params.mode === 'edit' ? '' : 'edit'})}
/>
<Button
    title="Go To Page1"
    onPress={() => {
        navigation.navigate('Page1',{ name: 'Devio' });
    }}
/>
const {navigation} = this.props;
const {state, setParams} = navigation;
const {params} = state;
const showText = params.mode === 'edit' ? '正在编辑' : '编辑完成';

@全新导航器react-navigation精讲

使用setParams 改变route params

class ProfileScreen extends React.Component {
  render() {
    const {setParams} = this.props.navigation;
    return (
      <Button
        onPress={() => setParams({name: 'Lucy'})}
        title="Set title name to 'Lucy'"
      />
     )
   }
}

@全新导航器react-navigation精讲

注意navigation.setParams改变的是当前页面的Params,如果要改变其他页面的Params可以通过NavigationActions.setParams完成,下文会讲到。

使用goBack返回到上一页面或指定页面

export default class Page1 extends React.Component {
    render() {
        const {navigation} = this.props;
        return <View style={{flex: 1, backgroundColor: "gray",}}>
            <Text style={styles.text}>欢迎来到Page1</Text>
            <Button
                title="Go Back"
                onPress={() => {
                    navigation.goBack();
                }}
            />
        </View> 
    }
}

@全新导航器react-navigation精讲

通过dispatch发送一个action

const resetAction = NavigationActions.reset({
    index: 0,
    actions: [
        NavigationActions.navigate({
            routeName: 'HomePage',
            params:{
                theme:theme,
                selectedTab:selectedTab
            },
        })
    ]
    })
navigation.dispatch(resetAction)

@全新导航器react-navigation精讲

NavigationActions

Navigate:

Navigatie action会使用Navigate action的结果来更新当前的state。

import { NavigationActions } from 'react-navigation'

const navigateAction = NavigationActions.navigate({
  routeName: 'Profile',
  params: {},
  action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)

@全新导航器react-navigation精讲

Reset:

Reset action删掉所有的navigation state并且使用这个actions的结果来代替。

import { NavigationActions } from 'react-navigation'

const resetAction = NavigationActions.reset({
  index: 0,
  actions: [
    NavigationActions.navigate({ routeName: 'Profile'})
  ]
})
this.props.navigation.dispatch(resetAction)

@全新导航器react-navigation精讲

使用场景比如进入APP首页后的splash页不在使用,这时可以使用NavigationActions.reset重置它。

index参数被用来定制化当前激活的route。举个例子:使用两个routes WelcomePage和HomePage给一个基础的stack navigation设置。为了重置route到HomePage,但是在堆栈中又存放在WelcomePage之上,你可以这么做:

import { NavigationActions } from 'react-navigation'

const resetAction = NavigationActions.reset({
    index: 1,
    actions: [
        NavigationActions.navigate({ routeName: 'WelcomePage'}),
        NavigationActions.navigate({ routeName: 'HomePage'})
    ]
});
this.props.navigation.dispatch(resetAction);

@全新导航器react-navigation精讲

Back

返回到前一个screen并且关闭当前screen.backaction creator接受一个可选的参数:

import { NavigationActions } from 'react-navigation'
const backAction = NavigationActions.back();
this.props.navigation.dispatch(backAction);

SetParams

通过SetParams我们可以修改指定页面的Params。

import { NavigationActions } from 'react-navigation'
const setParamsAction = NavigationActions.setParams({
    params: { title: 'HomePage' },
    key: 'id-1517035332238-4',
});

有很多小伙伴可能会问:navigation中有setParams为什么还要有NavigationActions.setParams?

我从两方面来回答一下这个问题:

  1. 在上文中讲到过navigation中有可能只有state与dispatch,这个时候如果要修改页面的Params,则只能通过NavigationActions.setParams了;
  2. 另外,navigation.setParams只能修改当前页面的Params,而NavigationActions.setParams可以修改所有页面的Params;

还有那些应用场景?

在导航器屏幕之外使用导航功能(巧用导航器的ref)

有一种场景:有的时候我们需要在导航器中所定义的屏幕之外使用导航器来做页面跳转。

下面就给大家讲解通过ref属性还获得navigation

示例看代码:

import { NavigationActions } from 'react-navigation';

const AppNavigator = StackNavigator(SomeAppRouteConfigs);

class App extends React.Component {
  someEvent() {
    // call navigate for AppNavigator here:
    this. navigation && this. navigation.dispatch(
      NavigationActions.navigate({ routeName: someRouteName })
    );
  }
  render() {
    return (
      <AppNavigator ref={nav => { navigation = nav; }} />
    );
  }
}

上述代码通过导航器的顶级节点ref属性获取到navigation,当上述代码的AppNavigator节点被渲染时,ref会被回调这是就可以获取到navigation了,需要提醒大家的是,这种用法对除StackNavigator之外的其他两种类型的导航器也是实用的哦;

上一篇 下一篇

猜你喜欢

热点阅读