加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

React Native导航器之react-navigation使用

发布时间:2020-12-15 05:09:12 所属栏目:百科 来源:网络整理
导读:在上一节Navigation组件,我们使用系统提供的导航组件做了一个跳转的例子,不过其实战能力不强,这里推荐一个超牛逼的第三方库:react-navigation。在讲react-navigation之前,我们先看一下常用的导航组件。 导航控件 常见的导航主要分为三种: 1.StackNavig

在上一节Navigation组件,我们使用系统提供的导航组件做了一个跳转的例子,不过其实战能力不强,这里推荐一个超牛逼的第三方库:react-navigation。在讲react-navigation之前,我们先看一下常用的导航组件。

导航控件

常见的导航主要分为三种:
1.StackNavigator :类似于普通的Navigator,屏幕上方导航栏
2.TabNavigator:obviously,相当于iOS里面的TabBarController,屏幕下方标签栏
3.DrawerNavigator:抽屉效果,左侧滑出这种效果。

在你使用navigation的每一个界面navigation都提供相关的属性和响应方法,常见的有:
navigate 定义跳转到另一个页面
调用此方法去链接你的其他界面,主要有以下参数:
·routeName- 目标路由名称,将在你的app router中注册
·params-将参数合并到目标router中
·action-(高级)sub-action ,如果该界面是一个navigator的话,将运行这个sub-action

例如:

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

    return (
      <View>
        <Text>This is the home screen of the app</Text>
        <Button
          onPress={() => navigate('Profile',{name: 'Brent'})}
          title="点击我跳转"
        />
      </View>
     )
   }
}

state当前路由状态

每个界面通过this.props.navigation.state去访问它的router,state其中包括了:
·routeName - router配置的名称
·key-用来区分router的唯一标示
·params-可选的一些string参数
setParams-更改router中的参数
该方法允许界面更改router中的参数,可以用来动态的更改header的内容
goBack-返回,pop回上一级
dispatch -使用dispatch可以向任何navigation传递一些其他的action,主要支持的action有

例如:

import { NavigationActions } from 'react-navigation'

const navigationAction = NavigationActions.navigate({
  routeName: 'Profile',params: {},// navigate can have a nested navigate action that will be run inside the child router
  action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigationAction)

Reset

Reset方法会擦除掉所有的导航状态,并且使用新的结果替代。

import { NavigationActions } from 'react-navigation'

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

SetParams

为指定的router更新参数,该参数必须是已经存在于router的param中。

import { NavigationActions } from 'react-navigation'

const setParamsAction = NavigationActions.setParams({
  params: {},// these are the new params that will be merged into the existing route params
  // The key of the route that should get the new params
  key: 'screen-123',})
this.props.navigation.dispatch(setParamsAction)

StackNavigator使用

StackNavigator使用比较简单,看一个常见的例子:

class MyHomeScreen extends React.Component {
  static navigationOptions = {
     title: 'Home',//设置navigator的title
  }

  render() {
    return (
      //button的onPress方法,实现点击跳转界面,并且传递参数name:Lucy
      <Button
        onPress={() => this.props.navigation.navigate('Profile',{name: 'Lucy'})}
        title="Go to Lucy's profile"
      />
    );
  }
}

//生成路由关系
const ModalStack = StackNavigator({
  Home: {
  //对应界面MyHomeScreen
    screen: MyHomeScreen,},Profile: {
    path: 'people/:name',screen: MyProfileScreen,});

StackNavigatorConfig

option for the route(路由选项):

·initialRouteName -为stack设置默认的界面,必须和route configs里面的一个key匹配。
·initialRouteParams - 初始路由的参数。
·navigationOptions- 屏幕导航的默认选项。
·paths-route config里面路径设置的映射。

Visual Option(视觉选项):

·mode- 定义渲染(rendering)和转换(transitions)的模式,两种选项:
1) card-使用标准的iOS和Android的界面切换,这是默认的。
2)modal- 仅在iOS端有用,即模态出该视图。

·headerMode- 指定header应该如何被渲染,选项:
1)float- 共用一个header 意思就是有title文字渐变效果。
2)screen- 各用各的header 意思就是没有title文字渐变效果。
3)none- 没有header。

·cardStyle- 使用该属性继承或者重载一个在stack中的card的样式。
·onTransitionStart- 一个函数,在换场动画开始的时候被激活。
·onTransitionEnd- 一个函数,在换场动画结束的时候被激活。

你还可以定义一个静态的navigationOptions在你的组件之上。

lass ProfileScreen extends React.Component {
  //设置navigation选项
  static navigationOptions = {
   //标题
    title: ({ state }) => `${state.params.name}'s Profile!`,//头部定义了一个右按钮,来改变edit的状态 ing或者完成
    header: ({ state,setParams }) => ({
      // Render a button on the right side of the header
      // When pressed switches the screen to edit mode.
      right: (
        <Button
          title={state.params.editing ? 'Done' : 'Edit'}
          onPress={() => setParams({editing: state.params.editing ? false : true})}
        />
      ),}),};
  ...

常用的配置中,主要有以下参数需要注意:
1)visible - bool值,header是否可见。
2)title-标题 String或者是一个react 节点
3)backTitle-返回按钮在iOS平台上,默认是title的值
4)right- react 节点显示在header右边,例如右按钮
5)left- react 节点显示在header左边,例如左按钮
6)style-header的style
7)titleStyle- header的title的style (^__^) 嘻嘻……
8)tintColor- header的前景色
·cardStack- 配置card stack

react-navigation

说完常见的导航器,我们在看看本文的重点:react-navigation的使用。
首先看一下效果:

1,在项目目录下,安装React-navigation库

npm install --save react-navigation

2,使用StactkNavigator来管理堆栈。暂且命名为HomeScreen.js。默认入口页面代码如下:

import React from 'react';
import {
  AppRegistry,Text,} from 'react-native';
//导入stack导航组件
import { StackNavigator } from 'react-navigation';

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Welcome',//标题
  };
  render() {
    return <Text>Hello,Navigation!</Text>;
  }
}
//导航注册
const SimpleApp = StackNavigator({
  Home: { screen: HomeScreen },});

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

运行效果:

3,添加一个新的页面

class ChatScreen extends React.Component {
  static navigationOptions = {
    title: 'Chat with Lucy',};
  render() {
    return (
      <View>
        <Text>Chat with Lucy</Text>
      </View>
    );
  }
}

4,在HomeScreen中添加一个button组件,使用routeName Chat关联到ChatScreen。

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

这段代码主要是给Button绑定onPress事件。这时候,我们使用的两个跳转的页面需要在StackNavigator进行注册:

const SimpleApp = StackNavigator({
  Home: { screen: HomeScreen },Chat: { screen: ChatScreen },//新添加的页面
});

所以完整的代码是:

class HomeScreen extends React.Component {  
    static navigationOptions = {  
        title: 'Welcome',//设置标题内容 
    };  

    render() {  
        const { navigate } = this.props.navigation;  
        return (  
            <View>  
                <Text>Hello,Navigation!</Text>  
                <Button  
                    onPress={() => navigate('Chat',{user:'Lucy'})}  
                    title="Chat with Lucy"/>  
            </View>  
        );  
    }  
}  

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

参数传递

在页面的跳转过程中,往往会伴随着参数的传递。

1,在第一个页面定义参数,将参数传值给需要传值的页面

constructor(props) { super(props); this.state = {};  
    } 
    ...
    if(navigator) { navigator.push({ name: 'SecondPageComponent',component: SecondPageComponent,params:{ user:this.state.user,pwd:this.state.pwd }  
            })  
        }

2,如果需要监听页面的state状态

onChangeText={(text) => this.setState({user: text})}

3,另一个页面接受参数

componentDidMount() {  
            //这里获取从FirstPageComponent传递过来的参数: id  
            this.setState({  
                user:this.props.user,pwd:this.props.pwd  
            }); 
    }

4,去的传过来的值:

value={this.state.user }

react-navigation参数传递

对于 react-navigation参数的传递,使用上比较简单,只需要在navigate中加一个json格式的对象即可,如:

navigate('Chat',{ user: 'Lucy' })

然后在接受的页面:

class ChatScreen extends React.Component {
  static navigationOptions = {
    // Nav options can be defined as a function of the navigation prop:
    title: ({ state }) => `Chat with ${state.params.user}`,};
  render() {
    // The screen's current route is passed in to `props.navigation.state`:
    const { params } = this.props.navigation.state;
    return (
      <View>
        <Text>Chat with {params.user}</Text>
      </View>
    );
  }
}

所以,你就可以看到如下的效果:

TabNavigator

TabNavigator类似于底部导航效果

// 注册tabs
const Tabs = TabNavigator({
    Home: {
        screen: Home,navigationOptions: {  // 也可以写在组件的static navigationOptions内
            tabBar: {
                label: '首页',icon: ({tintColor}) => (<Image source={require('./app/images/home.png')} style={[{tintColor: tintColor},styles.icon]}/>),}
    },Bill: {
        screen: Bill,navigationOptions: {
            tabBar: {
                label: '账单',icon: ({tintColor}) => (<Image source={require('./app/images/bill.png')} style={[{tintColor: tintColor},Me: {
        screen: Me,navigationOptions: {
            tabBar: {
                label: '我',icon: ({tintColor}) => (<Image source={require('./app/images/me.png')} style={[{tintColor: tintColor},}
    }
  },{
      animationEnabled: false,// 切换页面时是否有动画效果
      tabBarPosition: 'bottom',// 显示在底端,android 默认是显示在页面顶端的
      swipeEnabled: false,// 是否可以左右滑动切换tab
      backBehavior: 'none',// 按 back 键是否跳转到第一个Tab(首页), none 为不跳转
      tabBarOptions: {
          activeTintColor: '#ff8500',// 文字和图片选中颜色
          inactiveTintColor: '#999',// 文字和图片未选中颜色
          showIcon: true,// android 默认不显示 icon,需要设置为 true 才会显示
          indicatorStyle: {
              height: 0  // 如TabBar下面显示有一条线,可以设高度为0后隐藏
          },style: {
              backgroundColor: '#fff',// TabBar 背景色
              // height: 44
          },labelStyle: {
              fontSize: 10,// 文字大小
          },});

DrawerNavigator

DrawerNavigator类似于抽屉侧滑效果。

const DrawerNav = DrawerNavigator({
    Home: { screen: Home },Bill: { screen: Bill },Me: { screen: Me },HomeTwo: { screen: HomeTwo },HomeThree: { screen: HomeThree },HomeFour: { screen: HomeFour },BillTwo: { screen: BillTwo },BillThree: { screen: BillThree }
},{
    drawerWidth: 200,// 抽屉宽
    drawerPosition: 'left',// 抽屉在左边还是右边
    // contentComponent: CustomDrawerContentComponent,// 自定义抽屉组件
    contentOptions: {
      initialRouteName: Home,// 默认页面组件
      activeTintColor: 'white',// 选中文字颜色
      activeBackgroundColor: '#ff8500',// 选中背景颜色
      inactiveTintColor: '#666',// 未选中文字颜色
      inactiveBackgroundColor: '#fff',// 未选中背景颜色
      style: {  // 样式

      }
    }
});

iOS版设置

在iOS中使用react-navigation需要注意以下几点:
使用Xcode设置Schemes;
在AppDelegate添加一下代码:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
  return [RCTLinkingManager application:application openURL:url
                      sourceApplication:sourceApplication annotation:annotation];
}

js组件在注册路由时设置唯一的路径path,例如Home2: { screen: Home2,path:’app/Home2’ };
在手机浏览器访问demo4://app/Home2,弹窗选择打开,就可以打开demo4 app并进到Home2页面。

react-native-tab-navigator

直接上代码:

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

import React,{ Component } from 'react';
import TabNavigator from 'react-native-tab-navigator';
import {
  AppRegistry,StyleSheet,Image,View
} from 'react-native';

const TabNavigatorItem =TabNavigator.Item;
//默认选项
const TAB_HOME_NORMAL=require('./image/tabbar_homepage.png');
const TAB_MINE_NORMAL=require('./image/tabbar_mine.png');
//选中
const TAB_HOME_PRESS=require('./image/tabbar_homepage_selected.png');
const TAB_MINE_PRESS=require('./image/tabbar_mine_selected.png');

export default class HelloWord extends Component {
  //默认选中
  constructor(){
    super();
    this.state={
      selectedTab:'Home',}
  }
  //点击方法
  onPress(tabName){
   if(tabName){
     this.setState({
         selectedTab:tabName,}
     );
   }
 }

//渲染选项
 renderTabView(title,tabName,tabContent,isBadge){
      var tabNomal;
      var tabPress;
      switch (tabName) {
        case 'Home':
          tabNomal=TAB_HOME_NORMAL;
          tabPress=TAB_HOME_PRESS;
          break;
       case 'Mine':
        tabNomal=TAB_MINE_NORMAL;
        tabPress=TAB_MINE_PRESS;
        break;
        default:

      }
      return(
       <TabNavigatorItem
        selected={this.state.selectedTab===tabName}
        title={title}
        titleStyle={styles.tabText}
        selectedTitleStyle={styles.selectedTabText}
        renderIcon={()=><Image style={styles.icon} source={tabNomal}/>}
        renderSelectedIcon={()=><Image style={styles.icon} source={tabPress}/>}

        onPress={()=>this.onPress(tabName)}
        renderBadge={()=>isBadge?<View style={styles.badgeView}><Text style={styles.badgeText}>15</Text></View>:null}
        >
       <View style={styles.page}><Text>{tabContent}</Text></View>
       </TabNavigatorItem>
     );
   }

      //自定义TabView
    tabBarView(){
          return (
            <TabNavigator
             tabBarStyle={styles.tab}
            >
            {this.renderTabView('首页','Home','首页模块',true)}
            {this.renderTabView('我的','Mine','我的模块',false)}
            </TabNavigator>
          );
        }

  //渲染界面
  render() {
    var tabView=this.tabBarView();
    return (
      <View style={styles.container}>
             {tabView}
            </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  },tabText: {
        fontSize: 10,color: 'black'
    },selectedTabText: {
        fontSize: 10,color: 'green'
    },tab:{
    height: 52,alignItems:'center',backgroundColor:'#f4f5f6',tabIcon:{
    width:25,height:25,badgeView:{
    width:22,height:14,backgroundColor:'#f85959',borderWidth:1,marginLeft:10,marginTop:3,borderColor:'#FFF',justifyContent:'center',borderRadius:8,badgeText:{
    color:'#fff',fontSize:8,icon: {
        width: 22,height: 22
    },page: {
        flex: 1,justifyContent: 'center',alignItems: 'center',backgroundColor: '#FFFFFF'
    },});


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

参考:React Native页面参数传递
https://reactnavigation.org/docs/intro/

react-native-tab-navigator封装

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读