前言
很久没写东西了,发现时间过的真快。之前想学习下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的对接外,基本功能都完成了,不过必然还有很多地方做的不正确。所以欢迎同样正在学习的同学一起交流讨论,也欢迎熟手来指导。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。