React-Native 開發(fā)篇一React-Native+Redux開發(fā)框架搭建

前言:從事react-native開發(fā)一年半的時間了诽里,從最初的0.17版本開始接觸react-native到現(xiàn)在的0.51穩(wěn)定版啥刻,期間從一開始的看著官方文檔自我摸索到后來的漸漸社區(qū)龐大,各種組件層出不窮巾腕,react-native雖然越發(fā)成熟豫领,然而大版本的改動纪隙,新技術(shù)的更替往往讓人措手不及,從一開始的單頁面涵蓋組件碗硬,狀態(tài)以及后臺交互代碼瓤湘,到后來的組件拆分,說不上那種更好恩尾,但往往我們習(xí)慣學(xué)習(xí)大部分人的想法弛说,接觸了一段時間的redux之后,遠(yuǎn)遠(yuǎn)不及精通翰意,甚至有時候只是知其然而不知其所以然木人,然而生活總有新的東西要去做,最近要去搞vue了猎物,避免新的東西取代大腦里面舊的東西虎囚,暫切在此記錄以下react-native開發(fā)過程中的一些經(jīng)驗和總結(jié),以便以后查閱蔫磨。本文記錄使用redux狀態(tài)管理機(jī)制來配合react-native開發(fā)的一些過程淘讥。

一.項目初始化

react-native init reduxDemo

初始化完成后控制臺輸出如下信息:


二. 依賴安裝

必須依賴項:

  • npm install redux --save
  • npm install react-redux --save
  • npm install redux-thunk --save

擴(kuò)展依賴:

  • npm install immutable --save
  • npm install react-native-router-flux --save

三.項目結(jié)構(gòu)

  • src-項目文件總文件夾。
    -- src/modules-項目模塊文件夾堤如,按模塊規(guī)劃建立子文件夾蒲列,按每個模塊劃分項的state,reducer和action,(問題:按模塊劃分還是頁面單獨劃分為好?)如登錄授權(quán)模塊為auth搀罢。
    --- src/modules/auth-登錄授權(quán)模塊蝗岖。
    -- src/resource-整個項目資源文件,多為圖片榔至,問題:資源文件是放置到相應(yīng)的模塊文件夾下還是在此處統(tǒng)一管理抵赢,那種較好?不知道,大概各有各的好吧铅鲤。
    --src/actionTypes.js-整個項目操作定義划提。
    --src/appState.js-整個項目狀態(tài)統(tǒng)一管理。
    --src/actionStore.js-state中間件邢享。
    --src/actionReducer.js-整個項目reducer 統(tǒng)一管理鹏往。
    --src/actionRoot.js-項目路由管理。

四.核心代碼

  1. appState.js
import authState from './modules/auth/authState';

export default function getAppState () {
  const appState = {
    auth: new authState()
    //...其他模塊State
  }
  return appState;
}

備注:整個APP狀態(tài)匯總骇塘,開發(fā)時定義在各個模塊下伊履,此處由各個模塊文件引入做統(tǒng)一管理。

2.appTypes.js

export const LOGIN_SUCCESS  = 'LOGIN_SUCCESS';//登錄成功
export const LOGIN_FAILURE  = 'LOGIN_FAILURE';//登錄失敗

備注:reducer中更新狀態(tài)使用款违。

3.appReducer.js

import auth from './modules/auth/authReducer';
import { combineReducers } from 'redux';

const appReducer = combineReducers({
    auth
    //...其他模塊reducer
});
export default appReducer;

備注:整個APP Reducer匯總唐瀑,開發(fā)時定義在各個模塊下,此處由各個模塊文件引入做統(tǒng)一管理奠货。

4.appStore.js

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './appReducer';
import getAppState from './appState';

const createStoreWithMiddleware = applyMiddleware(thunk) (createStore);

function configureStore (initialState) {
    return createStoreWithMiddleware(reducer, initialState);
}
var appStore=configureStore(getAppState());
export default appStore;

5.appRoot.js

import React, { Component } from 'react';
import { Provider } from 'react-redux';
import {
    View,
    Text,
    BackAndroid
} from 'react-native';
import { Scene, Router, TabBar, Modal, Schema, Actions, Reducer, ActionConst } from 'react-native-router-flux';
import LoginPage from './modules/auth/containers/loginPage';

export default class AppRoot extends Component {
    constructor(props) {
        super(props);
    }

    createReducer(params) {
        const defaultReducer = Reducer(params);
        return (state, action) => {
          this.props.dispatch(action);
          return defaultReducer(state, action);
        };
    }

    onExitApp(){
        BackAndroid.exitApp();
        return true;
    }
    render() {
        return (
            <Router onExitApp={this.onExitApp} 
                    createReducer={ this.createReducer }
                    scenes={ scenes }
             >          
            </Router >
        )
    }    
}

const scenes = Actions.create(
    <Scene key="root" hideNavBar={true}>
        <Scene key="login" component={LoginPage} title="登錄" hideNavBar={true} initial />
    </Scene>
)

備注:APP路由管理頁面介褥。

6.App.js

import React, { Component } from 'react';
import { Provider } from 'react-redux';
import AppRoot from './src/appRoot';
import appStore from './src/appStore';

export default class App extends Component<{}> {
  constructor(props) {
    super(props);
  } 
  render() {
    return (
        <Provider store={appStore}>
            <AppRoot />
        </Provider>
    );
  }
}

備注:APP入口。

五.示例模塊

模塊結(jié)構(gòu):


項目結(jié)構(gòu)

1.state定義

import { Record, List } from 'immutable';

let authState = Record({
    isLogin:false
});

export default authState;

2.action定義

import * as types from '../../actionTypes';

export function login(userName,password) {
    return {
        type:types.LOGIN_SUCCESS
    }  
}

3.reducer定義

import AuthState from './authState';
import * as types from '../../actionTypes';
import Immutable, { Record, List } from 'immutable';

const authState = new AuthState();
export default function authReducer(state = authState, action) {
    switch (action.type) {
        case types.LOGIN_SUCCESS:
             return state.set('isLogin', true);
        case types.LOGIN_FAILURE:
             return state.set('isLogin', false);
        default: 
             return state;
    }
    return state;
}

4.component定義

import React, { Component } from 'react';
import { StyleSheet, Platform, TextInput, View, Dimensions, Text,ImageBackground, Image, TouchableOpacity } from 'react-native';

export default class LoginComponent extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (         
            <ImageBackground source={require('../../../resource/login-background.jpg')} resizeMode='stretch' style={[styles.stretch,styles.center]}>               
                <Image source={require('../../../resource/logo.png')} style={styles.logo}/>
                <TextInput placeholder='請輸入您的用戶名' style={styles.input}/>
                <TextInput placeholder='請輸入您的密碼' secureTextEntry={true} style={styles.input}/>
                <TouchableOpacity style={[styles.btn,styles.center]} onPress={this.props.onLogin}>
                    <Text style={styles.text}>登錄</Text>
                </TouchableOpacity>
            </ImageBackground>
        )
    }  
}

var {height, width} = Dimensions.get('window');
const styles = StyleSheet.create({
    logo:{
        width:80,
        height:80,
        marginBottom:50
    },
    center:{
        alignItems: 'center',
        justifyContent:'center'
    },
    stretch: {
        height:height,
        width:width   
    },
    input:{
        height:30,
        width:width*0.6,
        padding:0,
        borderBottomWidth:1,
        borderBottomColor:"#8ecbc1",
        paddingLeft:20,
        marginBottom:10
    },
    btn:{
        width:width*0.6,
        backgroundColor:"#8ecbc1",
        height:32,
        marginTop:20
    },
    text:{
        color:"#fff",
        fontSize:16
    }
});

5.container定義

import React, { Component } from 'react';
import LoginComponent from "../components/loginComponent"
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as authActions from '../authActions';

class LoginPage extends Component {
    constructor(props) {
        super(props);
    }

    componentWillReceiveProps(nextProps,nextState){
        if(nextProps.isLogin){
            alert("登錄成功");
        }
    }

    render() {
        return (
            <LoginComponent onLogin={this.props.actions.login}/>
        )
    }  
}

function mapStateToProps(state) {
    return {
        isLogin:state.auth.isLogin
    }
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(authActions, dispatch)
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(LoginPage);

六.參考資料


GIT源碼地址:react-native-demo 分支名稱:framework (git checkout framework)

個人博客:有恒則成

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末递惋,一起剝皮案震驚了整個濱河市柔滔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌萍虽,老刑警劉巖睛廊,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異杉编,居然都是意外死亡超全,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進(jìn)店門邓馒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘶朱,“玉大人,你說我怎么就攤上這事光酣∈瓒簦” “怎么了桶错?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵脾拆,是天一觀的道長。 經(jīng)常有香客問我癌蚁,道長唱遭,這世上最難降的妖魔是什么戳寸? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮拷泽,結(jié)果婚禮上疫鹊,老公的妹妹穿的比我還像新娘袖瞻。我一直安慰自己,他們只是感情好拆吆,可當(dāng)我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布虏辫。 她就那樣靜靜地躺著,像睡著了一般锈拨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上羹唠,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天奕枢,我揣著相機(jī)與錄音,去河邊找鬼佩微。 笑死缝彬,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的哺眯。 我是一名探鬼主播谷浅,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奶卓!你這毒婦竟也來了一疯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤夺姑,失蹤者是張志新(化名)和其女友劉穎墩邀,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盏浙,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡眉睹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了废膘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竹海。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖丐黄,靈堂內(nèi)的尸體忽然破棺而出斋配,到底是詐尸還是另有隱情,我是刑警寧澤孵稽,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布许起,位于F島的核電站,受9級特大地震影響菩鲜,放射性物質(zhì)發(fā)生泄漏园细。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一接校、第九天 我趴在偏房一處隱蔽的房頂上張望猛频。 院中可真熱鬧狮崩,春花似錦、人聲如沸鹿寻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毡熏。三九已至坦敌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痢法,已是汗流浹背狱窘。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留财搁,地道東北人蘸炸。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像尖奔,于是被迫代替她去往敵國和親搭儒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內(nèi)容