从0到1打造一款react-native App(二)Navigation+Redux

前言

好久没写东西了,发现时间过的真快。以前想学习下RN,可是因为本身的懒惰挖了个坑,最近正好公司开了RN的项目,我也把好久之前挖的坑填一下!新开的这个项目只有我一我的搞,以前没作过RN,此次正好能够边作边学,仍是很开心的,享受这种探索的过程。开始!react

App

图片描述

环境搭建好以后,就开始开发了。仍是先大体介绍下这个小项目,此次主要大体会完成如下几个功能:git

  1. 摄像头相关(二维码扫描,拍照摄像等等,相似微信拍照,可是拍出的照片要求不能在系统相册显示,所以会涉及到文件操做相关)。
  2. 地理信息(签到功能,后续可能会对接一款地图吧)。
  3. NFC(身份证,门禁卡读取)。
  4. 基础的展现页(长列表等等吧)。

这是目前的项目结构:
图片描述github

和以前搭的PC差很少,项目结构都千篇一概,多了一个navigation的文件夹。接下来就介绍这个。npm

Navigation

最初在搭建RN的项目,主要是参照react-native的文档,因此不少时候仍是不大清楚到底该用什么,好比路由。Navigation是网上说起比较多的应用包,所以本项目也使用了这个。redux

本项目用的navigation版本是v2.2.5,你们在用的时候必定要看清楚版本,不一样版本的api仍是有差别的,而后去看英文的文档,这里我还被坑了一下。ubuntu

navigation的路由入口是由一个StackNavigator建立的,也就如名字同样是一个堆栈式的路由数据,在2.2.5版本已经由StackNavigator变为createStackNavigator了。目前app只作了一个主页面和一个二维码扫描的跳转页。即:react-native

const AppNavigator = createStackNavigator(
        {
            Home: {
                screen: MainScreenNavigator,
                navigationOptions: {
                    title: '首页'
                }
            },
            QRcode: {
                screen: QRcode,
                navigationOptions: {
                    header: null
                }
            }
        }
);

主要的页面都写在了MainScreenNavigator。api

MainScreenNavigator用了一般app采用的底部tab的呈现方法,界面预览:
图片描述微信

在navigation中主要有两种导航的表现形式,一种是Tab navigation,另外一种是Drawer navigation,这里采用的tab的表现方式,而drawer 相似于侧边抽出的,目前尚未用到。目前下方的tab主要分为5个,即:app

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...

相关文章
相关标签/搜索