React Native填坑之旅 -- 使用react-navigation代替Navigator

简介:

Navigator已经被React Native废弃了。也许你可以在另外的一个依赖库里react-native-deprecated-custom-components里找到。不过既然官方推荐的是react-navigation那我们就来看看这个东西到底有什么好的,值不值得用。

一句话概括的话,react-navigation非常值得用。之前配置一个Navigator非常的繁琐,但是使用react-navigation的任何一个导航组件都非常简单。项目的github地址在这里

react-navigation包括下面三个Navigator:

  • StackNavigator: 这个组件是用来代替之前的Navigator的。凡是维持一种“先进后厨”的栈式导航的话就可以用这个。
  • TabNavigator:这个组件和iOS的`TabBarController。看起来是这样的。
  • DrawerNavigator:这个组件就是抽屉式的导航菜单。在React Native里只有Android才有:DrawerLayoutAndroid,在iOS里是没有的。有了DrawerNavigator,两个平台都可以用了。

我会在下文里主要介绍StackNavigatorDrawerNavigator。对于TabNavigatgor它的使用非常简单,当你回了前面的两种的时候你就自然可以搞定它了。

Stack Navigator

react-native init AwesomeProject

命令后生成的默认项目里,查看index.js文件:

import { AppRegistry } from 'react-native';
import App from './App';

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

APP开始执行后运行的就是App组件。也就是App.js文件export的是什么组件,App就运行什么组件。

App.js文件中,去掉export default。就如我们的demo做的一样,添加一个MessageContainer.js文件,并添加demo中的内容。这样在其中我们已经有了AppMessageContainer两个组件。

下面看下如何配置。

最简单的:

export default NavHome = StackNavigator({
  Home: {
    screen: NavApp,
  },
  Message: {
    screen: MessageContainer,
  },
})

导出StackNavigator方法生成的组件NavHome。运行起来之后,理论上就可以导航了。但是会有问题,因为这时还没有能够跳转的触发点。所以,我们还要做如下的修改。

修改App.js文件的内容。在其中添加一个按钮,点击之后可以进入到MessageContainer组件。修改MessageContainer.js文件,在里面添加一个按钮返回。

//App.js
<Button onPress={this.props.navigation.navigate('Message')} title={'To message'} />

//MessageContainer.js
<Button onPress={this.props.navigation.goBack()} title={'Go Back'} />

但是,这样还是demo的水平,离真正的产品级使用还差很多。一般的App,在push到下一个页面的时候会点击navigation bar的回退按钮返回上一页。我们就来实现这个功能。

使我们首先看一下StackNavigator的API:

StackNavigator(RouteConfigs, StackNavigatorConfig)

通过查看文档,要实现这个功能需要在RouteConfigs里面增加navigationOptions来达到。如下:

export default NavHome = StackNavigator({
  Home: {
    screen: App,
    navigationOptions: ({navigation}) => ({
      title: 'Home',
      headerLeft: (<Button onPress={() => navigation.navigate('DrawerToggle')} title={'User'} />),
      headerRight: (<Button onPress={() => navigation.navigate('Message')} title={'Message'} />),
    })
  },
  Message: {
    screen: MessageContainer,
    navigationOptions: ({navigation}) => ({
      title: "Message",
      headerLeft: (<Button title='Back' onPress={() => {navigation.goBack();}} />)
    })
  },
});

详细看一下navigationOptions

  1. title:是导航栏上显示的title。
  2. headerLeft: 是导航栏左侧的组件。我这里放了一个按钮。更好的是放置一个TouchableOpacity组件。因为按钮在iOS上还好,但是在Android上就是一个明晃晃的按钮啊,各种边框和阴影。
  3. headerRight: 是导航栏右侧的组件。

MessageContainer的导航栏上就只需要一个“返回”按钮,所以只有一个headerLeft就足够了。在首页上的导航栏的headerLeft是用来触发稍后讲到的DrawerNavigator的。

这样,这个靠谱的导航就完成了。


Drawer Navigator

DrawerNavigatorStackNavigator的配置很类似。

const NavApp = DrawerNavigator({
  Home: {
    screen: App,
  },
  MyWallet: {
    screen: MyWalletView,
  },
  MyVoucher: {
    screen: MyVoucherView,
  }
});

这个时候看起来是这样的:
normal_drawer_nav_top.png

但是我想要的效果是这样的:
drawer_top.png

显然,文档里提供的一些简单的定制是不能完成这样的效果的。于是,我们查看文档,发现有办法直接替换掉默认的Drawer实现,非常简单:

const NavApp = DrawerNavigator({
  Home: {
    screen: App,
  },
  User: {
    screen: UserContainer,
  },
  MyWallet: {
    screen: MyWalletView,
  },
  MyVoucher: {
    screen: MyVoucherView,
  }
}, {
   contentComponent: props => (<UserDrawer items={props} />)
})

看下API:

DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)

只要叫上DrawerNavigatorConfig配置里的contentComponent配置。也就是上面配置的第二个参数。

{
   contentComponent: props => (<UserDrawer items={props} />)
}

contentComponent就是drawer的内容组件。这里我们用的是UserDrawer组件,并把props传递了进去。

这样我们想要的抽屉式菜单就实现了。

StackNavigator和DrawerNavigator结合使用

现在把这两个组件结合在一起使用。在首页上的导航栏里的两个按钮,左侧的开启drawer导航,右侧的是“message”按钮,使用StackNavigator组件导航。

如果是在drawer导航里使用StackNavigator的话,那么只要这样配置:

export default NavHome = StackNavigator({
  Home: {
    screen: NavApp,
    navigationOptions: ({navigation}) => ({
      title: 'Home',
      headerLeft: (<Button onPress={() => navigation.navigate('DrawerToggle')} title={'User'} />),
      headerRight: (<Button onPress={() => navigation.navigate('Message')} title={'Message'} />),
    })
  },
  Message: {
    screen: MessageContainer,
    navigationOptions: ({navigation}) => ({
      title: "Message",
      headerLeft: (<Button title='Back' onPress={() => {navigation.goBack();}} />)
    })
  },
});

export default NavApp = DrawerNavigator({
  Home: {
    screen: NavHome, // ***
  },
  MyWallet: {
    screen: MyWalletView,
  },
  MyVoucher: {
    screen: MyVoucherView,
  }
}, {
   contentComponent: props => (<UserDrawer items={props} />)
})

要在Drawer导航里用stack导航,那么就在drawer导航里的某个路由选项里加上screen: NavHome。这个NavHome就是stack导航。反之,则是在stack导航里的某个route选项的screen上指定drawer导航。

但是在使用上还是有一点区别的。如果drawer导航里包含stack导航。那么drawer导航菜单的最高点是在屏幕的最高点。反之,如果drawer导航被stack导航包含的话,drawer导航菜单的最高点是在导航栏的下方的。如图:
drawer导航包含stack导航

drawer导航被stack导航包含

回到正题。从drawer导航菜单跳转到任何的页面后如何跳转回来呢?还是老方法:

export default class MyWalletView extends React.Component {
  render() {
    return (
      <TouchableOpacity 
        style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}
        onPress={() => this.props.navigation.goBack()}>
        <Text>{'My Wallet'}</Text>
      </TouchableOpacity>
    );
  }
}

调用props传入的navigation的方法来实现返回:

this.props.navigation.goBack()

总结

更多请看代码吧。留下来TabNavigator来给各位读者朋友实践一下练练手吧。其实配置的简单程度比早前React Native里的Navigator已经降低了很多了。

StackNavigator里还有除了navigate()goBack()两个方法之外,还有其他的一些方法可以调用。实际的App交互中也并不是只有导航到某一页,然后再从那一页跳转回来这么简单。后面有机会会讲到这方面的内容。

欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处!
























本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/p/7801671.html ,如需转载请自行联系原作者

相关文章
|
7月前
|
开发框架 前端开发 JavaScript
探索前端开发中的跨平台框架React Native
本文将介绍前端开发中一种备受关注的跨平台框架React Native,通过比较原生应用与React Native的优缺点,探讨其在实际项目中的应用以及未来发展趋势。
106 2
|
7月前
|
开发框架 前端开发 JavaScript
从零开始学习React Native开发
React Native是一种基于React框架的移动端开发框架,使用它可以快速地构建出高性能、原生的移动应用。本文将从零开始,介绍React Native的基础知识和开发流程,帮助读者快速入门React Native开发,并实现一个简单的ToDo应用程序。
|
7月前
|
开发框架 Dart 前端开发
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
【4月更文挑战第30天】对比 Flutter(Dart,强类型,Google支持,快速热重载,高性能渲染)与 React Native(JavaScript,庞大生态,热重载,依赖原生渲染),文章讨论了开发语言、生态系统、性能、开发体验、学习曲线、社区支持及项目选择因素。两者各有优势,选择取决于项目需求、团队技能和长期维护考虑。参考文献包括官方文档和性能比较文章。
254 0
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
|
5月前
|
前端开发 JavaScript Android开发
React Native跨平台开发实战
【7月更文挑战第21天】React Native为跨平台移动应用开发提供了一种高效且强大的解决方案。通过本文的学习,你应该能够掌握React Native的基本概念和实战步骤,并开始在你的项目中使用React Native进行开发。随着你对React Native的深入理解,你将能够利用其强大的功能来构建更加复杂和高效的移动应用。
|
7月前
|
开发框架 移动开发 前端开发
【Uniapp 专栏】Uniapp 与 React Native 的对比分析
【5月更文挑战第14天】Uniapp和React Native是热门的跨平台移动开发框架。Uniapp以其一套代码多端运行、丰富的组件生态和较低的学习曲线受到青睐,适合快速开发简单应用。React Native基于React,拥有活跃社区和优秀性能,适合复杂应用。React Native在性能上略胜一筹,尤其在需要接近原生体验的场景。Uniapp的官方组件弥补了社区资源不足。选择时需考虑开发效率、性能需求、团队技术栈和社区支持。
1996 1
【Uniapp 专栏】Uniapp 与 React Native 的对比分析
|
6月前
|
前端开发 自动驾驶 程序员
鸿蒙? 车载?Flutter? React Native? 为什么我劝你三思,说点不一样的
本文探讨了在信息技术快速发展的背景下,开发者如何选择学习路径。作者提倡使用终局思维来规划职业发展,考虑技术的长远影响。终局思维注重长远目标、系统分析、反向规划和动态调整。以车载开发为例,预测未来智能汽车可能由语音助手主导,而非依赖平板界面。此外,作者建议不要过分投入打工状态,应思考创建自己的产品,如App,以实现技能补充和额外收入。选择对未来发展和自主性有益的技术,如Kotlin,比盲目追求热点更为重要。做减法和有标准的选择,能帮助减轻焦虑,实现更高效的成长。关注公众号“AntDream”获取更多相关内容。
144 1
|
6月前
|
开发框架 前端开发 JavaScript
移动应用开发中的跨平台策略:Flutter与React Native的比较
在移动应用领域,跨平台解决方案已成为开发者追求高效、成本效益和广泛覆盖的关键。本文深入探讨了两种领先的跨平台框架——Flutter和React Native,从技术架构、性能、社区生态及实际应用案例四个维度进行全面对比分析。通过这一比较,旨在为移动应用开发者提供选择合适框架的参考依据,帮助他们根据项目需求做出明智的决策。
|
6月前
|
前端开发 iOS开发 Android开发
React Native跨平台开发实战:从零到一
学习React Native跨平台开发,首先安装Node.js和React Native CLI,设置Android/iOS环境。使用CLI创建项目,如`npx react-native init MyProject`。运行应用:`npx react-native run-android`或`run-ios`。编写组件,如在App.js中创建Hello World。添加样式,安装第三方库如react-native-vector-icons,使用react-navigation进行路由和导航。
116 2
|
7月前
|
前端开发 JavaScript Android开发
使用React Native开发跨平台移动应用的技术详解
【5月更文挑战第22天】本文详述了使用React Native开发跨平台移动应用的技术,该框架由Facebook推出,基于JavaScript,支持iOS和Android。React Native通过JNI/JSI实现JavaScript到原生代码的转换,提供高效性能和原生体验。其优势包括跨平台性、原生体验、开发速度及社区支持。开发流程涉及环境搭建、项目创建、编码、调试与测试,以及构建与发布。注意事项包括性能优化、平台适配、利用第三方库和持续学习。React Native为开发者构建高质量跨平台应用提供了便捷途径,未来潜力无限。
|
6月前
|
Dart 前端开发 JavaScript
探索移动应用开发中的跨平台解决方案:Flutter与React Native的比较
在移动应用开发领域,选择合适的跨平台解决方案是关键。本文将深入分析Flutter和React Native这两大主流框架,从性能、开发效率、社区支持等方面进行比较,帮助开发者做出明智的选择。
86 0