本文主要是以我的另一篇文章的思維過程來操作,希望大家使用后可以記住整個(gè)過程,從而活學(xué)活用,使用到自己的項(xiàng)目中.
參考文章:react-native中使用redux的原理分析及demo
demo地址:github.com/NextChampion/react-native-redux-navigation-example
react native 已更新到0.57.8版本
效果圖
demo簡(jiǎn)單介紹:
功能:登錄頁(yè)中點(diǎn)擊登錄,跳轉(zhuǎn)到主頁(yè),主頁(yè)內(nèi)含有一個(gè)大家都很熟悉的counter組件.可以實(shí)現(xiàn)簡(jiǎn)單的加減數(shù)操作;
demo邏輯:
登錄:
點(diǎn)擊登錄時(shí),組件的點(diǎn)擊方法會(huì)發(fā)送消息到action內(nèi),
action將該消息預(yù)處理,即區(qū)分一下type,然后返回給store,
store將分好類的消息,分配到reducer中處理state.
reducer接收到帶有type的消息以后,找到對(duì)應(yīng)的處理辦法,生成新的state返回給store,
store控制頁(yè)面渲染,跳轉(zhuǎn)到主頁(yè);
加減:
點(diǎn)擊加號(hào),組件將該點(diǎn)擊方法發(fā)送到action內(nèi),
action預(yù)處理該消息,區(qū)分是加/減,指定type后,返回消息給store;
store收到預(yù)處理后的消息后,將該消息發(fā)送給reducer;
reducer收到store發(fā)過來的消息,根據(jù)消息內(nèi)的type處理數(shù)據(jù),真正進(jìn)行加/減過程,并且將新的state返回給store;
store收到reduder發(fā)過來的新state,控制頁(yè)面渲染,即頁(yè)面中數(shù)字的變化;
demo特點(diǎn):
1.區(qū)分登錄和加減邏輯,并且將不同的state對(duì)應(yīng)不同的組建部分
登錄相關(guān)的state只有l(wèi)oginPage可用,加減相關(guān)的state只有主頁(yè)面可用;
2.頁(yè)面切換使用react-navigation控制;
3.該demo大家可以拿去改改部分代碼,直接類比內(nèi)部redux的邏輯實(shí)現(xiàn)過程,開發(fā)自己的項(xiàng)目;
下面開始詳細(xì)講解整個(gè)demo的實(shí)現(xiàn)過程
1.新建項(xiàng)目
react-native init CountersDemo
2.安裝redux相關(guān)文件
npm install --save redux
npm install --save react-redux
npm install --save react-navigation
npm install --save redux-thunk
3.建立項(xiàng)目?jī)?nèi)部文件夾
4.redux相關(guān)代碼實(shí)現(xiàn)過程
1)新建src文件夾存放所有js文件.
2)新建constants,actions,reducers,store,container,pages文件夾
3)(設(shè)定類型type) constans文件夾內(nèi)新建文件loginType,用來劃分登錄過程中的事件類別
export const LOGIN_IN_DOING = 'LOGIN_IN_DOING'; //正在登陸
export const LOGIN_IN_DONE = 'LOGIN_IN_DONE'; // 登陸完成
export const LOGIN_IN_ERROR = 'LOGIN_IN_ERROR'; // 登陸出錯(cuò)
4.(設(shè)定預(yù)處理消息過程)actions文件夾內(nèi),新建loginAction文件,用來給預(yù)處理消息區(qū)分各個(gè)事件的類別
'use strict';
import * as types from '../constants/loginTypes';// 導(dǎo)入事件類型,用來做分配給各個(gè)事件
// 模擬用戶信息
let user = {
name: 'zhangsan',
age: 24,
}
// 訪問登錄接口 根據(jù)返回結(jié)果來劃分action屬于哪個(gè)type,然后返回對(duì)象,給reducer處理
export function login() {
console.log('登錄方法');
return dispatch => {
dispatch(isLogining()); // 正在執(zhí)行登錄請(qǐng)求
// 模擬用戶登錄
let result = fetch('https://www.baidu.com/')
.then((res)=>{
dispatch(loginSuccess(true,user)); // 登錄請(qǐng)求完成
}).catch((e)=>{
dispatch(loginError(false)); // 登錄請(qǐng)求出錯(cuò)
})
}
}
function isLogining() {
return {
type: types.LOGIN_IN_DOING
}
}
function loginSuccess(isSuccess, user) {
console.log('success');
return {
type: types.LOGIN_IN_DONE,
user: user,
}
}
function loginError(isSuccess) {
console.log('error');
return {
type: types.LOGIN_IN_ERROR,
}
}
5.(設(shè)定消息的具體處理過程)reducers文件夾內(nèi)新建loginReducer文件,用來處理登錄過程中的state變化
'use strict';
import * as types from '../constants/loginTypes'; // 導(dǎo)入事件類別,用來做事件類別的判斷
// 初始狀態(tài)
const initialState = {
status: '點(diǎn)擊登錄',
isSuccess: false,
user: null,
}
// 不同類別的事件使用switch對(duì)應(yīng)處理過程
export default function loginIn(state=initialState, action) {
switch (action.type) {
case types.LOGIN_IN_DOING:
return {
...state,
status: '正在登陸',
isSuccess: false,
user: null,
}
break;
case types.LOGIN_IN_DONE:
return {
...state,
status: '登陸成功',
isSuccess: true,
user: action.user,
}
break;
case types.LOGIN_IN_ERROR:
return {
...state,
status: '登錄出錯(cuò)',
isSuccess: true,
user: null,
}
break;
default:
return state;
}
}
6).項(xiàng)目?jī)?nèi)可能并不是只有一個(gè)redux操作邏輯,現(xiàn)在給所有的reducer建立一個(gè)統(tǒng)一的入口
reducers文件夾內(nèi)新建index.js文件,作為統(tǒng)一入口;
(由于本篇文章是demo寫好后整理的,所以現(xiàn)在這里不應(yīng)該有counterReducer,大家在參考本文時(shí),這里只寫login的內(nèi)容即可)
'use strict';
import { combineReducers } from 'redux';
import loginIn from './loginReducer'; // 導(dǎo)入登錄的redux處理過程
const rootReducer = combineReducers({ // 將所有的redux處理邏輯包裝在一起
loginIn: loginIn,
});
export default rootReducer; // 導(dǎo)出,作為統(tǒng)一入口
7).創(chuàng)建項(xiàng)目中的store,用來管理所有的state
store文件夾內(nèi)新建ConfigureStore.js文件
'use strict';
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import rootReducer from '../reducers/index';
const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore);
export default function configureStore(initialState) {
const store = createStoreWithMiddleware(rootReducer, initialState)
return store;
}
8).現(xiàn)在action,reducer,store都存在了,按照我另一篇原理分析內(nèi)的非視圖部分已基本完成.
接下來我們?cè)谔幚硪晥D部分,即Provider.在這里我個(gè)人習(xí)慣從外層往內(nèi)寫.先寫Provider外殼,并將整個(gè)APP包裹在內(nèi);
src文件夾內(nèi),新建Root.js文件,該文件內(nèi)實(shí)現(xiàn)Provider對(duì)視圖部分的包裹
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import configureStore from './store/ConfigureStore';
import App from './container/App';// app的入口
const store = configureStore();
export default class Root extends Component {??
? ? render() {? ??
? ? ? ? return (
? ? ? ? ? ? <Provider store={store}>
? ? ? ? ? ? ? ? <App />
? ? ? ? ? ?</Provider>
? ? ? ? )?
? ? }
}
import App from './container/App';這里對(duì)應(yīng)的是 app的入口 寫到這里的時(shí)候,本文件還沒有實(shí)現(xiàn)
9).實(shí)現(xiàn)視圖的部分代碼
container文件夾內(nèi)新建App.js文件,作為整個(gè)app的入口;
此處使用了react-navigation用來管理頁(yè)面;
import React, { Component } from 'react';
import {
View,
Text,
} from 'react-native';
import { StackNavigator } from 'react-navigation';
import LoginPage from '../pages/LoginPage'
import MainPage from '../pages/MainPage'
const App = StackNavigator({
Login: { screen: LoginPage },
Main: { screen: MainPage},
});
export default App
10.實(shí)現(xiàn)頁(yè)面(注意此處有很關(guān)鍵的一步,需要在頁(yè)面內(nèi)實(shí)現(xiàn)組件和store的關(guān)聯(lián),之所以能夠?qū)崿F(xiàn)不同的組件關(guān)聯(lián)不同的state也是在這一步進(jìn)行的)
此處代碼量較多,只粘貼關(guān)鍵代碼
class LoginPage extends Component {?
?static navigationOptions = {? ? title: 'LoginPage',? };??
shouldComponentUpdate(nextProps, nextState) {? ??
// 登錄完成,切成功登錄? ?
?if (nextProps.status === '登陸成功' && nextProps.isSuccess) {? ? ??
this.props.navigation.dispatch(resetAction)? ? ?
?return false;? ?
?}? ??
return true;??
}?
?render() {? ??
const { login } = this.props;? ??
return(
/*...components*/
)?
?}
}
export default connect(
(state) => ({
status: state.loginIn.status,
isSuccess: state.loginIn.isSuccess,
user: state.loginIn.user,
}),
(dispatch) => ({
login: () => dispatch(loginAction.login()),
})
)(LoginPage)
11).請(qǐng)大家自行實(shí)現(xiàn)加減法部分的邏輯并將其關(guān)聯(lián)到對(duì)應(yīng)的頁(yè)面內(nèi).
1.設(shè)定時(shí)間的所有處理類別; type
2.事件預(yù)處理過程; action
3.事件處理過程; reducer
4.通過reducer統(tǒng)一入口導(dǎo)出供外部使用;
5.實(shí)現(xiàn)視圖pages并將其與邏輯部分綁定到一起;connect
可查閱demo代碼
希望本文對(duì)大家有所幫助
有問題歡迎大家留言評(píng)論,會(huì)盡快回復(fù)的