从0到1打造一款react-native App(二)Navigation+Redux
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/j_bleach/article/details/80714844
前言
很久没写东西了,发现时间过的真快。之前想学习下RN,但是由于自己的懒惰挖了个坑,最近正好公司开了RN的项目,我也把很久以前挖的坑填一下!新开的这个项目只有我一个人搞,之前没做过RN,这次正好可以边做边学,还是很开心的,享受这种探索的过程。开始!
App
环境搭建好之后,就开始开发了。还是先大致介绍下这个小项目,这次主要大致会完成以下几个功能:
- 摄像头相关(二维码扫描,拍照摄像等等,类似微信拍照,但是拍出的照片要求不能在系统相册显示,因此会涉及到文件操作相关)。
- 地理信息(签到功能,后续可能会对接一款地图吧)。
- NFC(身份证,门禁卡读取)。
- 基础的展示页(长列表等等吧)。 这是目前的项目结构:
和之前搭的PC差不多,项目结构都千篇一律,多了一个navigation的文件夹。接下来就介绍这个。
Navigation
最初在搭建RN的项目,主要是参照react-native的文档,所以很多时候还是不大清楚到底该用什么,比如路由。Navigation是网上提及比较多的应用包,因此本项目也使用了这个。
本项目用的navigation版本是v2.2.5,大家在用的时候一定要看清楚版本,不同版本的api还是有差异的,然后去看英文的文档,这里我还被坑了一下。
navigation的路由入口是由一个StackNavigator创建的,也就如名字一样是一个堆栈式的路由数据,在2.2.5版本已经由StackNavigator变为createStackNavigator了。目前app只做了一个主页面和一个二维码扫描的跳转页。即:
const AppNavigator = createStackNavigator(
{
Home: {
screen: MainScreenNavigator,
navigationOptions: {
title: '首页'
}
},
QRcode: {
screen: QRcode,
navigationOptions: {
header: null
}
}
}
);
主要的页面都写在了MainScreenNavigator。
MainScreenNavigator用了通常app采用的底部tab的呈现方法,界面预览:
在navigation中主要有两种导航的表现形式,一种是Tab navigation,另一种是Drawer navigation,这里采用的tab的表现方式,而drawer 类似于侧边抽出的,目前还没有用到。目前下方的tab主要分为5个,即:
const MainScreenNavigator = createMaterialBottomTabNavigator(
{
Home: {
screen: Home,
navigationOptions: {
title: '首页',
tabBarIcon: tabBarIcon('home')
}
},
Photo: {
screen: Photo,
navigationOptions: {
title: '拍照',
tabBarIcon: tabBarIcon('photo-album')
}
},
NFC: {
screen: Setting,
navigationOptions: {
title: 'NFC',
tabBarIcon: tabBarIcon('credit-card')
}
},
Upload: {
screen: Upload,
navigationOptions: {
title: '上传',
tabBarIcon: tabBarIcon('cloud-upload'),
}
},
Setting: {
screen: Setting,
navigationOptions: {
title: '设置',
tabBarIcon: tabBarIcon('settings')
}
}
},
{
shifting: true,
backBehavior: 'none',
initialRouteName: 'Home',
activeTintColor: '#ffffff',
inactiveTintColor: '#eeeeee',
barStyle: {
backgroundColor: '#4177F6',
paddingBottom: 20,
height: 50
}
}
);
这个tab用到了他官方推荐的一个react-navigation-material-bottom-tabs
插件,在使用这个插件时需要去引入icons,我这里引入的是这个。
顺便说一下,react-native推荐的包管理工具是yarn,最好使用yarn可以省很多事,因为我这边(ubuntu16.04)如果用npm安装的话,就不能正常使用react link xx的功能,link是帮我们自动去关联一些依赖以及gradle的。
navigation的一些配置可以在creat的时候去写,比如声明一个tab的名称为上传。
Upload: {
screen: Upload,
navigationOptions: {
title: '上传',
tabBarIcon: tabBarIcon('cloud-upload'),
}
},
也可以在具体的业务组件里面去定义静态方法,如:
class Upload extends PureComponent {
static navigationOptions = {
tabBarOnPress: async ({ defaultHandler, navigation }) => {
const { navigate } = navigation;
const files = await storageFile();
navigate('Upload', { files });
}
};
}
比如在点击Upload的tab时,去触发一个存储文件的方法(storageFile是自定义的方法)。
这里我个人觉得一些静态的title,或者样式上的配置,就直接在总的MainScreenNavigator中写好就行了,而涉及到一些具体的业务需求,方法,就在具体的组件模块里去写,比较方便管理和维护。
navigation大体介绍到这里,之后有在项目中新增的东西,会继续同步过来。
Redux
最初在项目搭建的时候,还是像将redux引入react 的方式,去引入到react-native的。即用react-redux提供的Provider在根页面将app包裹起来,然后去把reducer注入到store当中去。但是有些情况下,可能需要navigation的配合,因此需要去整合navigation进来。
在navigation v2.2.5中将很多api独立了出来,单独分了一个react-navigation-redux-helpers
的模型。大体思路还是没有变,根页面引入react-redux。
import React, {
Component
} from 'react';
import { Provider } from 'react-redux';
import store from './redux/store';
import Navigation from './navigation';
import { YellowBox } from 'react-native';
YellowBox.ignoreWarnings(['Warning: isMounted(...) is deprecated', 'Module RCTImageLoader']);
class App extends Component {
render() {
return (
<Provider store={store}>
<Navigation />
</Provider >
);
}
}
export default App;
在store当中增加对navigation的整合:
import { createStore, combineReducers, applyMiddleware } from 'redux';
import * as reducer from '../reducer/';
import thunk from 'redux-thunk';
import AppNavigator from '../../navigation/route';
import { createNavigationReducer, createReactNavigationReduxMiddleware } from "react-navigation-redux-helpers"; // 中间件,有了这个就可以支持异步action
const navReducer = createNavigationReducer(AppNavigator);
const middleware = createReactNavigationReduxMiddleware(
"root",
state => state.nav
);
const store = createStore(
combineReducers({ ...reducer, nav: navReducer }),
applyMiddleware(middleware)
);
export default store;
navigation组件去做一些初始属性的配置:
import React, {
Component
} from 'react';
import { connect } from 'react-redux';
import {
createNavigationPropConstructor, // handles #1 above
initializeListeners, // handles #4 above
} from 'react-navigation-redux-helpers';
import AppNavigator from './route.js';
const navigationPropConstructor = createNavigationPropConstructor("root");
class Navigation extends Component {
componentDidMount() {
initializeListeners("root", this.props.nav);
}
render() {
this._navigation = navigationPropConstructor(
this.props.dispatch,
this.props.nav,
AppNavigator.router,
() => this._navigation
);
return (
<AppNavigator navigation={this._navigation} />
);
}
}
const mapStateToProps = (state) => ({
nav: state.nav,
});
export default connect(mapStateToProps)(Navigation);
关于navigation+redux我这里就没有去细讲了,因为自己也是完全去照搬官方文档,如果有同学去做到这一块的话,以官方文档为参考就ok。
在做navigation这一块,个人感觉还是比较简单好理解的,唯一不好的地方是版本之间差异较大,最初v2.2.5开发完之后,去重新下载项目依赖,navigation往上升了2个小版本,结果就不行了,而这中间也就隔了3,4天而已,所以配置相关的东西还是要去看最新的文档。
目前这个项目自己做了一个星期左右,大体功能除了地图sdk的对接外,基本功能都完成了,不过必然还有很多地方做的不正确。所以欢迎同样正在学习的同学一起交流讨论,也欢迎熟手来指导。
项目地址:https://github.com/jiwenjiang/react-native-nfc
- 常用 Git 命令清单
- 如何将配置spring文件指定名字,指定位置
- 基础篇章:React Native 之 TextInput 的讲解
- Linux下 标准错误输出重定向
- CentOs6.5 修改主机名
- 基础篇章:React Native 之 View 和 Text 的讲解
- CentOs7.3 修改主机名
- 基础篇章:React Native之Flexbox的讲解(Height and Width)
- PDF.js专题
- CentOs7.3 编译安装 Nginx 1.9.9
- 基础篇章:关于 React Native 之 RefreshControl 组件的讲解
- CentOs7.3 安装 JDK1.8
- 基础篇章:关于 React Native 之 ListView 组件的讲解
- maven环境快速搭建
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 原创 | 随机数大家都会用,但是你知道生成随机数的算法吗?
- 原创 | codeforces 1425E,一万种情况的简单题
- 原创 | codeforces 1417C,逆向思考的数据结构题
- 原创 | 操作失误不要慌,这个命令给你的Git一次反悔的机会
- 原创 | 想做推荐算法?先把FM模型搞懂再说
- 活见鬼,明明删除了数据,空间却没减少!
- 原创 | Git仓库的提交记录乱成一团,怎么办?
- 原创 | 平面内有N个点,如何快速求出距离最近的点对?
- 原创 | codeforces 1426F,初学者也能做,div3的最难题
- 安全研究 | YARA规则阻止Windows事件日志记录
- 研究人员如何使用Shhgit搜索GitHub中的敏感数据
- 使用nProbe监控移动网络(2G,3G和LTE)
- Mykings僵尸网络新变种已感染超5万台电脑
- 谁告诉你鸿蒙(HarmonyOS)不能在macOS下玩,一副没见过世面的样子!
- 连Python产生器(Generator)的原理都解释不了,还敢说Python用了5年?