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

相關文章
相關標籤/搜索