前言:從事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-項目路由管理。
四.核心代碼
- 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):
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)
個人博客:有恒則成