Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

ReactNative开发——Navigation的使用

$
0
0

ReactNative开发——Navigation的使用

React Native 0.43之前 ‘react-native’包里面,但0.43之后了’rea移除了rect-native’。网上的大部分资料,也是ReactNative 0.43之前的 Navigator的用法,然而我用的0.44版本在开发,这就….
参考: http://facebook.github.io/react-native/docs/navigation.html

安装 ‘react-navigator’依赖

于是我按着文档 https://reactnavigation.org/docs/intro/ 来安装:

在项目目录下执行命令安装:

npm install --save react-navigator

结果呵呵哒:

E:\hybrid\react_native_pro\Project02>npm install
npm WARN peerDependencies The peer dependency react@* included from react-navigation will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency react@* included from react-native-drawer-layout-polyfill will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency react@* included from react-native-tab-view will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm ERR! install trying to install 15.5.4 to E:\hybrid\react_native_pro\Project02\node_modules\react-navigation\node_modules\react
npm ERR! install but already installed versions [ '15.5.4' ]
npm ERR! Windows_NT 10.0.14393
npm ERR! argv "D:\\Program Files\\nodejs\\node.exe" "C:\\Users\\Administrator\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js" "install"
npm ERR! node v4.4.7
npm ERR! npm  v2.15.12
npm ERR! code EPEERINVALID

npm ERR! peerinvalid The package react@16.0.0-alpha.6 does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer react-native@0.44.0 wants react@16.0.0-alpha.6
npm ERR! peerinvalid Peer react-navigation@1.0.0-beta.11 wants react@*
npm ERR! peerinvalid Peer react-test-renderer@16.0.0-alpha.6 wants react@^16.0.0-alpha.6

npm ERR! Please include the following file with any support request:
npm ERR!     E:\hybrid\react_native_pro\Project02\npm-debug.log```

最后我的解决办法是 安装npm3:

npm install -g npm@3

然后重新执行上面的命令安装。

开始学习

HelloWorld

首先根据官方文档的实例代码编写出来看看效果:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

'user react'

import React, {Component} from 'react';
import {AppRegistry, View, Button, Text} from 'react-native';
import {StackNavigator} from 'react-navigation'

/**
 * 主页面
 */
class HomeScreen extends Component {
    static navigationOptions = {
        /*设置标题*/
        title: 'Welcome'
    }

    render() {
        const {navigate} = this.props.navigation;

        return (
            <View>
                <Text> Hello,Navigator</Text>
                <Button
                    title="Chat With Lucy"
                    //跳转第二个页面,第二个参数,向第二个页面传入参数{user:'Lucy'}
                    onPress={() => navigate('Chat', {user: 'Lucy'})}
                >
                </Button>
            </View>
        );
    }
}

/**
 * 第二个页面
 */
class ChatScreen extends Component {
    /*可以定义一个函数来读取上个页面传过来的参数*/
    static navigationOptions = (({navigation}) => ({
        title: `Chat with ${navigation.state.params.user}`
    }))

    render() {
        const { params } = this.props.navigation.state;

        return (
            <View>
                <Text> Hello , {params.user}</Text>
            </View>
        );
    }
}

const Project02 = StackNavigator({
    Home: {screen: HomeScreen},
    Chat: {screen: ChatScreen},
});

AppRegistry.registerComponent('Project02', () => Project02);

该代码实现了:
1.定义了2个页面 HomeScreen和ChartScreen。在HomeScreen中有个按钮,点击跳转到到第二个页面并传参。

介绍

Navigators是用来定义为你应用顶用导航架构用的,你也可以通过配置让它为您渲染公共的元素,比如头部或者TabBar。

用来构建Navigator的函数
  • StackNavigator —— 用来提供类似“栈”的那张导航,比如启动一个页面,这个新的页面覆盖在旧的页面上,继续按返回键这个新的页面将“弹出”又出现旧的页面。
  • TabNavigator —— 提供一个TabBar让用户在几个页面之前切换,这种类似:以Android为例,效果等于TabLayout+ViewPager+Fragment那种。
  • DrawerNavigator ——提供一个抽屉,左滑出现。
使用Navigators

使用Navigators我们主要学习2个属性,下文Screen指的是我们的页面组件(即上文,HelloWorld中的HomeScreen,和ChildScreen等)
* Screen navigation prop ,我们可以使用它来调用导航操作,比如启动另一个页面。
* Screen navigationOptions, 我们可以用来定义navigator的显示属性,比如(title,tab label等)

在顶层组件使用导航

上面一个条目,我们讲到用 screen 的 navigation prop可以进行导航操作,但如果我们要在外部操作导航怎么办呢?
我们可以这样:声明一个Navigators的引用,我们可以使用这个引用进行操作,例如:

const AppNavigator = StackNavigator(SomeAppRouteConfigs);

class App extends React.Component {
    someEvent() {
        // call navigate for AppNavigator here:
        this.navigator && this.navigator.dispatch({ type: 'Navigate', routeName, params });
    }
    render() {
        return (
            <AppNavigator ref={nav => { this.navigator = nav; }} />
        );
    }
}

注意,这种解决方案应该只用在最顶层的navigator。

当navigation prop没有设置的时候,这个Navigation会自动显示在顶层,她将是一个透明的容器。
当渲染navigaor的时候,这个navigation props 是可选的,如果不设置,它也会有一些默认的操作,比如可以处理URL,外部链接、android会返回键等。这是因为这些系统自带的navigator(StackNavigator、TabNavigator)他们内部使用了createNavigationContainer方法,通常,这个方法被用来设置 navigator prop 去支持一些函数。

顶部Navigators接受以下属性:
onNavigationStateChange(prevState, newState, action)
这个用来获得Navigation的状态,它可以接收前一个状态,和最新的状态,以及操作

uriPrefix
用来设置url的前缀,表示那些url可以被我们的app处理。

下面,我贴一个例子,来演示以下 uriPrefixonNavigationStateChange(prevState, newState, action)的用法

/**
 * Created by Administrator on 5/27/2017.
 */

import React from 'react';
import {
    AppRegistry,
    Text,
    View,
    Button,
} from 'react-native';
import {TabNavigator, StackNavigator} from 'react-navigation';

class RecentChatsScreen extends React.Component {
    render() {
        return <Text>List of recent chats</Text>
    }
}

class AllContactsScreen extends React.Component {
    render() {
        return (
            <View>
                <Text>Hello, Chat App!</Text>
                <Button
                    onPress={() => this.props.navigation.navigate('Chat', {user: 'Lucy'})}
                    title="Chat with Lucy"
                />
            </View>
        );
    }
}

class ChatScreen extends React.Component {
    static navigationOptions = ({navigation}) => {
        const {state, setParams} = navigation;
        const isInfo = state.params.mode === 'info';
        const {user} = state.params;
        return {
            title: isInfo ? `${user}'s Contact Info` : `Chat with ${user}`,
            headerRight: (<Button title={isInfo ? 'Done' : `${user}'s Info`}
                                  onPress={() => setParams({mode: isInfo ? 'none' : 'info'})}
            />)
        };
    };


    render() {
        const {params} = this.props.navigation.state;
        return (
            <View>
                <Text>Chat with {params.user}</Text>
            </View>
        );
    }
}


const MainScreenNavigator = TabNavigator({
    Recent: {
        screen: RecentChatsScreen
    },
    All: {
        screen: AllContactsScreen,
    },
});


// MainScreenNavigator.navigationOptions = {title: "Main"};

const SimpleApp = StackNavigator({
    // 使用 header:null 去掉StackNavigator的导航栏头部
    Home: {screen: MainScreenNavigator, navigationOptions: ({navigation}) => ({header: null}),},
    Chat: {
        screen: ChatScreen,
        //路径,user为可以接受的参数
        path: 'chat1/:user',

    }
})


const MainApp = () => <SimpleApp
    //设置 URL's  Schema,和 Host
    uriPrefix={'chat://chat/'}
    onNavigationStateChange={(preState, newState, action) => {
        console.log('preState:' + JSON.stringify(preState)
            + ',newState:' + JSON.stringify(newState) + ',action:' + JSON.stringify(action));
    }}/>
AppRegistry.registerComponent('Project05', () => MainApp);

上述代码设置了 uriPrefix为 ‘chat://chat/,并设置了 ChatScreen中的 path为: chat1/:user, 其中:user`表示接受参数 user
那么我们可以使用外部的URL来启动这个页面,
我们以Android为例,还需要在AndroidMainifest.xml中的Activity添加一下Intent-Filter。

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.DEFAULT"></category>
    <data android:scheme="chat"
          android:host="chat"></data>
</intent-filter>

安装成功之后,我们在命令行输入:adb shell am start -W -a android.intent.action.VIEW -d "chat://chat/chat1/blueberry"
就可跳转到ChatScreen那个页面了,并传入了参数为blueberry

相关的ios也可以用外部URL访问本应用的页面,可以参考:https://reactnavigation.org/docs/guides/linking

StackNavigator

StackNavigator用来解决屏幕跳转,用它的效果页面导航效果|类似于栈,新启动的页面覆盖在原先的页面上。

使用
/**
 * Created by blueberry on 6/15/2017.
 */

import React, {Component} from 'react';
import {StyleSheet, View, Button, Text, AppRegistry} from 'react-native';
import {StackNavigator} from 'react-navigation';

class MainScreen extends Component {
    static navigationOptions = {
        title: 'Home',
    }

    render() {
        return (
            <View style={{justifyContent: 'center', alignItems: 'center'}}>
                <Text>{this.props.navigation.state.params.content || ''}</Text>
                <Button title="Go to Profile"
                        onPress={() => this.props.navigation.navigate('Profile', {
                            title: 'blueberryTitle',
                            content: 'blueberryContent'
                        })}/>
            </View>
        );
    }
}

class Profile extends Component {
    static navigationOptions = ({navigation}) => ( {
        title: navigation.state.params.title,
    })

    render() {
        return (
            <View>
                <Text>{this.props.navigation.state.params.content}</Text>
            </View>
        );
    }
}

const App = StackNavigator(
    /**
     * 路由配置
     */
    {
        Home: {screen: MainScreen},
        Profile: {screen: Profile, navigationOptions: {headerRight: null}},
    },

    /**
     * StackNavigator配置,也可以省略。
     */
    {
        // 配置初始化路由名称
        initialRouteName: 'Home',
        // 配置初始化路由的参数
        initialRouteParams: {content: '初始化传入的参数'},
        // 配置默认的 navigationOptions
        navigationOptions: {headerRight: <Text>右边Header</Text>},
        // 转场动画开始的回到
        onTransitionStart: () => {
            console.log('start')
        },
    }
);

AppRegistry.registerComponent('Project05', () => App);
API 定义

StackNavigator(RouteConfigs, StackNavigatorConfig)

这个函数接受2个参数,RouteConfigs和StackNavigatorConfig,其中StatckNavigatorConfig可以省略,如果省略,则默认选择RouteConfigs中定义的第一个路由。

RoutConfigs

这个路由配置类,是一个Map结构,key是路由的明城,value 是路由的配置。


StackNavigator(
    {   // 以下定义了一个路由,Profile为路由的名称,对应的值则是路由的配置
        Profile: {
            // `ProfileScreen` 是一个 React UI组件的定义,它就是这个路由的界面
            screen: ProfileScreen,// 当 `ProfileScreen` 被StackNavigator加载之后,他将会有一个`navigation` 属性。


            // 这个是一个可选项,如果想让这个界面可以被外部链接启动,可以设置这个,:name是用来传入参数的,这个上文讲过。
            path: 'people/:name',


            // 设置这个可以覆盖我们在React Component中设置的navigationOptions属性
            navigationOptions: ({navigation}) => ({
                title: `${navigation.state.params.name}'s Profile'`,
            }),
        },


        ...MyOtherRoutes,
    });
StackNavigatorConfig
属性 作用
initialRouteName 设置初始化路由名称
initialRouteParams 设置初始化路由的参数
navigationOptions 设置默认的 navigationOptions (这个参数下文将要介绍)
paths map结构,覆盖在路由配置中的path
mode 定义渲染的和跳转动画的风格,可以设置为card,modal。默认为card。modal可以使界面跳转的而动画是从底部逐渐显示到整个屏幕,这个只对ios有效,因为android,默认转场动画就是从底部逐渐显示到真个屏幕
headerMode 指定如何渲染头部,可以设置为float,screen,none。如果设置为none,则不会有头部;如果设置为float, 页面跳转时,header是一直在顶部,而且如果header变化了的话,会有动画,有点像android的共享动画;设置成screen的话,头部是跟随这新的页面重新出现。
cardStyle 可以给页面设置style
transitionConfig 一个函数类型,可以用来配置转厂动画
onTransitionStart 函数类型,动画开始后的回调
onTransitionEnd 函数类型,动画结束时的回调
Screen Navigation Options
属性 作用
title string类型,如果设置了它,如果headerTitle或tabBarBabel没有设置的话,将默认会使用这个值
header React Eelement或 是一个参数是HeaderProps返回Rect Element类型的函数类型。它用来显示为header,设置null的话,可以隐藏header
headerTitle string 或者 React Element类型,用来设置header,默认显示的 title
headerBackTitle string 类型,用来设置在ios上显示黑色按钮,设置null不显示,默认是title
headerTruncatedBackTitle string 类型, 用来设置黑色按钮,当headerBackTitle没有充满屏幕的时候。
headerRight React Element类型,用来在Header右边添加控件
headerLeft React Element类型,用来在Header左边添加控件
headerStyle 设置header的样式
headerTitleStyle 用来设置title组件的样式
headerBackTitleStyle 用来设置黑色Title的样式
headerTintColor 用来设置header的颜色
headerPressColorAndroid 用来设置涟漪效果的颜色,android>5.0有效
gesturesEnabled 开启的话,你可以用手势 关闭页面,ios默认是true,Android默认是false。我用android机开启该选项,不知道用手势什么关~~。这TM就尴尬了~

我们创建StackNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用
* screenProps 给StackNavigator传入该属性,这个属性将继续传递StackNavigator中的screens,例如:

const SomeStack = StackNavigator({
    // config
});

<SomeStack
    screenProps={/* 这个属性将传递给屏幕组件,在屏幕组件使用 this.props.screenProps就可以访问 */}
/>

注意这个键一定要是 screenProps,别的可不行哟。

TabNavigator

用这个可以实现几个屏幕之间相互切换,(类似于android原生,TabLayout+Fragment 页面切换那种效果)。

使用
/**
 * Created by blueberry on 6/15/2017.
 */

import React, {Component} from 'react';
import {StyleSheet, AppRegistry, View, Button, Image,} from 'react-native';
import {TabNavigator, TabBarBottom, TabView, TabBarTop} from 'react-navigation';

class HomeScreen extends Component {
    static navigationOptions = {
        tabBarLabel: 'Home',
        tabBarIcon: ({tintColor}) => (<Image source={require('./img/chat_online_talk.png')}
                                             style={[styles.icon, {tintColor: tintColor}]}
        />),
    };

    render() {
        return (
            <Button title="Go to Notification" onPress={() => this.props.navigation.navigate('Notifications')}/>
        );
    }
}

class NotificationScreen extends Component {
    static navigationOptions = {
        tabBarLabel: 'Notifications',
        tabBarIcon: ({tintColor}) => (<Image source={require('./img/notification.png')}
                                             style={[styles.icon, {tintColor: tintColor}]}
        />),
        // 也可以是其他React Element,
        // tabBarIcon: ({tintColor}) => (<Button title="按钮" onPress={() => {
        // }}/>),
    }
    ;

    render() {
        return (
            <Button title="Go back home" onPress={() => this.props.navigation.goBack()}/>
        );
    }
}

var styles = StyleSheet.create({
    icon: {width: 26, height: 26}
});

const App = TabNavigator(
    {
        Home: {screen: HomeScreen},
        Notifications: {screen: NotificationScreen}
    },

    {
        tabBarOptions: {
            //激活的tab tint颜色
            activeTintColor: '#e91e63',
            //没有激活的tab tint颜色
            inactiveTintColor: 'black',
            //大写转换
            upperCaseLabel: true,
            //显示icon
            showIcon: true,
        },
        // android默认是TabBarTop,ios默认是TabBarBottom,
        tabBarComponent: TabBarBottom,
        // 可以为 top,bottom,用来决定TabBar放置的位置
        tabBarPosition: 'bottom',
        //设置是否可以滑动
        swipeEnabled: true,
        //切换时是否欧动画效果
        animationEnabled: false,
        // 是否懒渲染tabs
        lazy: false,
        //第一个被加载的路由名称
        initialRouteName: 'Home',
        //路由名称数组
        order: ['Home', 'Notifications'],
        paths: {Home: 'home', Notifications: 'Notifications'},
        backBehavior: true,
    }
);

AppRegistry.registerComponent('Project05', () => App);
Api 定义

TabNavigator(RouteConfigs,TabNavigatorConfigs)

RouteConfigs

这个和StackNavigator的RouteConfigs一样,上文已经讲过,用来设置路由信息。

TabNavigatorConfig
属性 作用
tabBarComponent 用来设置tab bar的组件,ios默认是TabBarBottom,android默认是TabBarTop
tabBarPosition 用来设置tabBar的位置,可以为 ‘top’ 或者’bottom’
swipeEnable 用来设置是否可以滑动切换
animateEnable 用来设置是否有动画效果
lazy 用来设置是否“懒渲染”tabbar
tabBarOption 用来设置tabBar的一些属性,颜色、样式等等,下文将要介绍
initialRouteName 初始化路由的名称
order 路由名称数组
paths 提供一个map,可以路由对应的path
backBehavior 如果设置为true,那么上面的例子,在第二个页面,按返回将不能反会到前一个页面,也就是是this.props.navigation.goBack()’不会起作用
TabBarBottom 的 tabBarOptions 设置
属性 作用
activeTintColor 激活的tab的tint 颜色,tint颜色值,icon和Label的颜色
activeBackgroundColor 激活tab的背景颜色
inactiveTintColor 没被激活的tint颜色
inactiveBackgroundColor 没被激活的tab的背景色
showLabel 是否显示label,默认是true
style tab bar的样式
labelStyle label的样式
tabStyle tab的样式
TabBarTop 的 tabBarOptions设置
属性 作用
activeTintColor 激活的tab的tint 颜色,tint颜色值,icon和Label的颜色
inactiveTintColor 没被激活的tint颜色
showIcon 是否显示icon,默认是false
showLabel 是否显示label,默认是true
upperCaseLabel 是够开启大写转换,默认是true
pressColor 按压颜色,涟漪效果,andorid>5.0有效
pressOpacity 按压颜色,透明度变换,android<5.0 和ios可用。
scrollEnabled tabs是够可以滑动
tabStyle tab的样式
indicatorStyle 底部指示器的样式
labelStyle label的样式
iconStyle icon的样式
style tab bar的样式

举个栗子:

tabBarOptions: {
    labelStyle: {
        fontSize: 12,
    },
    tabStyle: {
        width: 100,
    },
    style: {
        backgroundColor: 'blue',
    },
}
Screen Navigation Options
属性 作用
title 标题,如果headerTitle,和tabBarLabel,不设置的话,就默认是title
tabBarVisible 决定隐藏还是显示tab bar
tabBarIcon 可以是一个React Eclement,或者是一个参数为{focused:boolean,tintColor:string}返回Rect Element的函数,用来显示在Tab Bar上
tabBarLabel string类型,或者React Element类型,或者是参数为{focused:boolean,tintColor:string}返回React Element的函数

我们创建TabNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用
* screenProps 给TabNavigator传入该属性,这个属性将继续传递TabNavigator中的screens。这个和StackNavigator的用法一样,可以参考上文。

DrawerNavigator

这个导航是个抽屉效果,就是类似于QQ那种左滑菜单

使用
/**
 * Created by blueberry on 6/15/2017.
 */

import React, {Component} from 'react';
import {AppRegistry, StyleSheet, View, Button, Image, ScrollView} from 'react-native';
import {DrawerNavigator, DrawerItems} from 'react-navigation';

class HomeScreen extends Component {
    static navigationOptions = {
        drawerLabel: 'Home',
        drawerIcon: ({tintColor}) => (<Image
            style={[styles.icon, {tintColor: tintColor}]}
            source={require('./img/chat_online_talk.png')}/>),

    }

    render() {
        return (
            <View>
                <Button title="Go to notifications" onPress={() => this.props.navigation.navigate('Notifications')}/>
                <Button title="打开抽屉" onPress={() => this.props.navigation.navigate('DrawerOpen')}/>
                <Button title="关闭抽屉" onPress={() => this.props.navigation.navigate('DrawerClose')}/>
            </View>
        );
    }
}

class NotificationScreen extends Component {
    static navigationOptions = {
        drawerLabel: 'notifications',
        drawerIcon: ({tintColor}) => (<Image
            style={[styles.icon, {tintColor: tintColor}]}
            source={require('./img/notification.png')}/>),
    }

    render() {
        return (
            <Button title="Go back home" onPress={() => this.props.navigation.goBack()}/>
        );
    }
}

const App = DrawerNavigator(
    {Home: {screen: HomeScreen}, Notifications: {screen: NotificationScreen}},

    //一下是DrawerNavigator 的配置
    {
        // 设置宽度
        drawerWidth: 300,
        // 设置从右边拉出,还是左边拉出
        drawerPosition: 'left',
        //默认的的值是 DrawerItems,我们也可以自己配置组件
        contentComponent: props => <ScrollView
            style={{borderWidth: 1, borderColor: 'red'}}><DrawerItems {...props}/></ScrollView>,
        contentOptions: {
            items: ['Home', 'Notification'],
            activeItemKey: 'key',
            activeTintColor: '#ff863f',
            activeBackgroundColor: '#d0caff',
            inactiveTintColor: '#000000',
            inactiveBackgroundColor: '#fffcf8',
            //这个设置了没起作用,android,api 0.45
            onItemPress: (route) => {
                console.log('TAG' + JSON.stringify(route))
            },
            style: null,
            labelStyle: null,
        },

        // initialRouteName:'Notifications',
    }
    )
;

var styles = StyleSheet.create({
    icon: {width: 26, height: 26}
});
AppRegistry.registerComponent('Project05', () => App);

可以使用一下操作,打开或关闭抽屉

this.props.navigation.navigate('DrawerOpen'); // open drawer
this.props.navigation.navigate('DrawerClose'); // close drawer
Api定义

DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)

RouteConfigs

这个和StackNavigator一样,可以参考上文。

DrawerNavigatorConfig
属性 作用
drawerWidth 抽屉的宽度
drawerPosition 枚举值可以为‘left’或’rigt’表示抽屉是在左边还是右边
contentComponent 可以自定义显示drawer item的组件,默认是实现是DrawerItem
contentOptions drawer 内容的一些设置,背景颜色,tint颜色等等,下文将会讲到
DrawerItems 的contentOptions
属性 作用
items 路由的数组
activeItemKey 正在活动的路由的key
activeTintColor 正在活动的 item tint 颜色
activeBackgroundColor 正在活动的item的 背景颜色
inactiveTintColor 不在活动的item的 tint颜色
inactiveBackgroundColor 不在活动的item 的背景颜色
onItemPress(route) 设置一个函数,item被按下时,这个函数将被调用
style Dawer的样式
labelStyle label的样式
Screen Navigation Options
属性 作用
title 标题,如果headerTitle,和tabBarLabel,不设置的话,就默认是title
tabBarVisible 决定隐藏还是显示tab bar
tabBarIcon 可以是一个React Eclement,或者是一个参数为{focused:boolean,tintColor:string}返回Rect Element的函数,用来显示在Tab Bar上
tabBarLabel string类型,或者React Element类型,或者是参数为{focused:boolean,tintColor:string}返回React Element的函数

这个跟StackNavigator 和 TabNavigator的方式一样,可以参考上文。

Screen中的 Navigation 属性

每个Screen都会接收这样一个属性,它其中包含了以下对象:

  • navigate 用来跳转到其它页面。
  • state 屏幕当前的 state/routes 里面包含有路由信息和参数信息。
  • setParams 可以用来改变参数信息。
  • goBack 用来关闭当前的活动页面,并返回。
  • dispatch 给路由发送一个action。

    下面来逐个讲解喽~

它的函数形式为:
navigate(routeName, params, action)
- routeName 要跳转的页面路由名称。
- params 参数信息。
- action 高级用法~,逐个子 action运行在child路由,如果要跳转的页面也是一个Navigator的话。

state

页面可以通过 this.props.navigation.state获得,它的形式为:


{
    // 路由的名称
    routeName: 'profile',
        //唯一的id
        key: 'main0',
    // 参数
    params: { hello: 'world' }
}
setParams

改变路由的参数

例如:

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

关闭当前页面,并返回

示例:

class HomeScreen extends React.Component {
    render() {
        const {goBack} = this.props.navigation;
        return (
            <View>
                <Button
                    onPress={() => goBack()}
                    title="Go back from this HomeScreen"
                />
                <Button
                    onPress={() => goBack(null)}
                    title="Go back anywhere"
                />
                <Button
                    onPress={() => goBack('screen-123')}
                    title="Go back from screen-123"
                />
            </View>
        )
    }
}
dispatch

给路由发送一个action。用个栗子(没有什么比看代码来的简单明了了)。

/**
 * Created by blueberry on 6/15/2017.
 */

import React, {Component} from 'react';
import {AppRegistry, View, Button, Image, Text} from 'react-native';
import {NavigationActions, TabNavigator} from 'react-navigation';

class MainScreen extends Component {
    render() {
        return (
            <View>
                <Button title="跳转到Child页面" onPress={() => this.props.navigation.navigate('Child')}/>
                <Text>{this.props.navigation.state.params ? this.props.navigation.state.params.title : ''}</Text>
            </View>
        );
    }
}

class ChildScreen extends Component {


    render() {
        const navigationActions = NavigationActions.navigate({
            routeName: 'Home',
            params: {title: 'blueberryTitle'}

        });
        return (
            <View>
                <Button title="返回" onPress={() => this.props.navigation.goBack()}/>
                <Button title="返回Home显示title" onPress={() => this.props.navigation.dispatch(navigationActions)}/>
            </View>
        );
    }
}


const App = TabNavigator(
    {Home: {screen: MainScreen,}, Child: {screen: ChildScreen}}
);

AppRegistry.registerComponent('NavigationUsage', () => App);

上面核心代码:

 const navigationActions = NavigationActions.navigate({
            routeName: 'Home',
            params: {title: 'blueberryTitle'}

        });
 this.props.navigation.dispatch(navigationActions)

NavigationActions创建了一个acionts,然后使用dispatch去执行了,上面的执行效果就是,挑战到了Home页面,并传入了参数{title:'blueberryTitle'}

上文已经简单延时了navigation.dispatch()的用法。
它支持的action有:

  • navigate 跳转到其他路由
  • Rest 使用一个新的State替换当前的state。
  • Back 返回到前一个状态
  • Set Params 给你个路由设置 参数。
  • Init 如果state没有定义,使用它初始化第一个状态。

用法:

import { NavigationActions } from 'react-navigation'

const navigateAction = NavigationActions.navigate({

    routeName: 'Profile',

    params: {},

    action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})

this.props.navigation.dispatch(navigateAction)
属性 作用
routeName 路由名称
params 参数
action 高级用法,如果他要跳转的路由也是一个Navigator,用可以用来设置那个Navigator的action
Reset

用来重新设置路由记录

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

注意 index的值 必须在0 - actions.lenght的范围内,不能越界,指定当前在栈中的位置。

Back

使用方法:

const backAction = NavigationActions.back({
    key: 'Profile'
})
this.props.navigation.dispatch(backAction)

key为路由的唯一身份,但是我设置了以后,使用this.props.navigation.dispatch()没有效果,不设置的话,可以返回,我使用的Andorid机测试。

SetParams
const setParamsAction = NavigationActions.setParams({
    params: { title: 'Hello' },
    key: 'screen-123',
})
this.props.navigation.dispatch(setParamsAction)
  • parmas 为参数
  • key 为要修改的路由的身份

Screen Navigation Options

配置navigatinOptions

可以用2中方法来设置 navigationOptions

静态配置

示例:


class MyScreen extends React.Component {
    static navigationOptions = {
        title: 'Great',
    };
...
动态配置

示例:

class ProfileScreen extends React.Component {
    static navigationOptions = ({ navigation, screenProps }) => ({
        title: navigation.state.params.name + "'s Profile!",
        headerRight: <Button color={screenProps.tintColor} {...} />,
    });

这个函数接收的参数为props,props参数中包含 navigation,screenProps ,navigationOptions。返回值用来决定设置的navigationOpiotns。

参数的结构如下:
+ Props
- navigation
- screenProps
- navigationOptions

一般的Navigation Options 配置方法
class MyScreen extends React.Component {
    static navigationOptions = {
        title: 'Great',
    };
...
其他的配置方法
可以在配置路由的时候设置:

const SimpleApp = StackNavigator({
    // 使用 header:null 去掉StackNavigator的导航栏头部
    Home: {screen: MainScreenNavigator, navigationOptions: ({navigation}) => ({header: null}),},
    Chat: {
        screen: ChatScreen,
        //路径,user为可以接受的参数
        path: 'chat1/:user',

    }
},{})
还可以在Navigation 配置中设置
const App = StackNavigator(
    /**
     * 路由配置
     */
    {
        Home: {screen: MainScreen},
        Profile: {screen: Profile, navigationOptions: {headerRight: null}},
    },

    /**
     * StackNavigator配置,也可以省略。
     */
    {

        navigationOptions: {headerRight: <Text>右边Header</Text>},

    }
);

示例代码地址

https://github.com/blueberryCoder/RNDemo/tree/master/NavigationUsage

参考

https://reactnavigation.org/docs/intro/headers

作者:a992036795 发表于2017/6/16 10:52:00 原文链接
阅读:17 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>