title: 關(guān)于Redux為核心的應(yīng)用開發(fā)簡(jiǎn)介
date: 2017-04-20 08:05:04
categories: React-native
tags: Redux
問題出發(fā)點(diǎn),當(dāng)我們?cè)赨I組件中執(zhí)行交互操作(點(diǎn)擊,滑動(dòng)诵竭,提交),我們要考慮到怎么來(lái)響應(yīng)操作.函數(shù)式編程里有個(gè)圖,有一個(gè)機(jī)器,從一邊放入肉,另一邊出火腿.這就是一個(gè)流程.application的操作其實(shí)就是解決
點(diǎn)擊=>結(jié)果展示
的流程.
但是實(shí)際流程中需要解決的問題很多.我們要考慮怎么來(lái)更好的管理application 的狀態(tài)問題. 具備javascript的基礎(chǔ)知識(shí),幾個(gè)模式設(shè)計(jì)的東西严就,函數(shù)式編程的知識(shí),React的知識(shí),Redux的思想.可以說(shuō)想在實(shí)際應(yīng)用中玩轉(zhuǎn)React/Redux/Redux-saga/immutable策泣。需要掌握的東西還是很多的.
我先寫一點(diǎn)具體的一些學(xué)習(xí)內(nèi)容和需要的思想.
輔助觀念轉(zhuǎn)變的一個(gè)生活實(shí)例
先看個(gè)電燈電路
- 控制開關(guān)執(zhí)行動(dòng)作(操作),
- 電燈根據(jù)開關(guān)的動(dòng)作來(lái)改變狀態(tài),
- 電燈的狀態(tài)不是由自己決定的,電路里有電了就會(huì)亮,沒電了就不亮,像木偶一樣受到控制.
飛機(jī)座艙
各個(gè)儀表都和自己的傳感器連接在一起跟束,加上冗余備份的儀表,很難設(shè)計(jì)和維護(hù)
80-90年代的window操作系統(tǒng)(不止windows奧),起源其實(shí)就是早期美國(guó)國(guó)防部的科研項(xiàng)目.
傳感器和顯示屏就沒有那么多線了.由數(shù)據(jù)總線來(lái)做集中統(tǒng)一處理.
理解React/Redux/Redux-saga架構(gòu)的基礎(chǔ)知識(shí)
函數(shù)式編程思想
函數(shù)式編程把流程拆為幾個(gè)有聯(lián)系的步驟,可以分解流程,易于維護(hù).合起來(lái)完成一個(gè)具體的任務(wù).
但是這只是函數(shù)式編程的一個(gè)組成部分
在javascript的函數(shù)式編程中用到很多概念
- 函數(shù)作為一類對(duì)象,可以作為數(shù)組的元素,可以作為函數(shù)的參數(shù)來(lái)傳遞.
- 基于流的編程(
redux-saga就是基于流的編程
).
-
閉包的概念
- high-order function 接受其他函數(shù)作為參數(shù)的函數(shù)
- 純函數(shù),對(duì)象的immutable,狀態(tài)改變.
一個(gè)實(shí)際的流程分析
在用戶提交表單的時(shí)候莺奸,我們想要做如下事情:
1.
校驗(yàn)一些輸入信息 (簡(jiǎn)單丑孩, 寫在組件里)
Validate方法,可以考慮導(dǎo)入redux-form組件,自帶驗(yàn)證方法
2.
驗(yàn)證以后可以讓提交按鈕改為可以提交狀態(tài)了
```
//login.UI.js登錄組件
this.props.dispatch(userLoginRequest(submit_info));
//已經(jīng)結(jié)束了,不要想太多,用戶和組件的交互就是表單輸入和提交按鈕
//所以這里也執(zhí)行這個(gè)過(guò)程就可以了.
```
3.
彈起提示信息(React組件化的優(yōu)勢(shì),公共組件)
```
//login.Ui.js
//Lodaing組件
this.props.isFetching?<Loading>:null
```
4.
提交后端服務(wù) (我們用fetch,這個(gè)是不變的,redux只是對(duì)流程的控制,并不是要改變實(shí)際做事的方法)
5.
拿到后端返回狀態(tài) (promise resolve)
6.
隱藏提示信息 (鴻門宴啊,摔杯為號(hào),這不就是狀態(tài)嗎温学?)
```
//login.UI.js
this.props.isFetching?<Loading>:null
```
7.
更新redux store (reducer的操作)
//login.reducer.js
return state.merge(resolve.result);
8.
登錄界面的任務(wù)完成了.根據(jù)業(yè)務(wù)需要跳轉(zhuǎn)到對(duì)應(yīng)的頁(yè)面
//reducer.js
return state.merge(resolve.result);
//login.js
this.props.loginsuccess?(Action.Mycenter):(Action.refresh)
這里我們就把登錄的流程做了分解.好處是很多的,流程都是根據(jù)狀態(tài)來(lái)的變化的,
代碼書寫清晰,在每一步的dubug和測(cè)試過(guò)程都很容易,因?yàn)槲覀兛梢垣@取每一步的狀態(tài)
由于有redux-logger的中間件存在,我們還可以查看每一步的狀態(tài)變化.好像還有圖形化的界面來(lái)顯示state的變化.
總的原則是React組件只負(fù)責(zé)信息展示枫浙,簡(jiǎn)單的驗(yàn)證
復(fù)雜的邏輯現(xiàn)在全部在Redux中來(lái)實(shí)現(xiàn)
副作用(side effect)到底是個(gè)什么?
副作用其實(shí)就可以理解為由外部API提供的服務(wù).這個(gè)服務(wù)和我們的app的流程是沒有關(guān)系的,我們只需要給接口提供參數(shù),等待接口返回?cái)?shù)據(jù)就可以了.
React/Redux/Redux-saga
React的概念,原理
-
React內(nèi)心是虛擬DOM,在react中的html代碼實(shí)際是React渲染的模板
- React渲染動(dòng)態(tài)內(nèi)容的方式通過(guò)外部父組件傳入的props和組件內(nèi)部的state來(lái)實(shí)現(xiàn)
絕對(duì)不可以搞錯(cuò)的概念:組件之間要傳遞參數(shù)只能通過(guò)props來(lái)實(shí)現(xiàn),state只能在組件內(nèi)部使用,如果要把sate傳遞到其他組件,一定要經(jīng)過(guò)轉(zhuǎn)換
在React中,props和state都有兩類不同的id來(lái)區(qū)分,不同的id類型是找不到對(duì)方的內(nèi)容的.Redux的mapStateToProps方法就是把State的類型id轉(zhuǎn)為props的類型id.
由此可以得出什么結(jié)論呢紧帕?
其實(shí)Redux也是一個(gè)React的組件.
******切記,切記*******
3.Connect這個(gè)函數(shù)是非常重要的函數(shù)
組件要訂閱state的變化,能夠訂閱dispatch的方法都是通過(guò)connect函數(shù)來(lái)執(zhí)行的.
Redux的出現(xiàn)
Redux負(fù)責(zé)把React的邏輯處理獨(dú)立出來(lái)處理
Redux的要點(diǎn)有:
- 一個(gè)應(yīng)用只有一個(gè)state
- state是只讀的,這是immutable的概念.
- 修改state只能是用純函數(shù)來(lái)執(zhí)行,dispatch(Action(params))
一旦React的應(yīng)用中加入Redux的構(gòu)架以后魂挂,所有Appliction的核心就由組件轉(zhuǎn)變到Redux中了.如果和傳統(tǒng)的web的 browser/server來(lái)類比,Redux就變成了服務(wù)器的角色,state就承擔(dān)了數(shù)據(jù)庫(kù)的角色.
組件之前的state的改變現(xiàn)在要重新思考了.
組件之間就最好再也不要做數(shù)據(jù)的傳遞,組件要執(zhí)行渲染的sate統(tǒng)一從Redux的store中獲取
.
這一步思考方法的改變是極為重要的.
如果一個(gè)流程的過(guò)程非常的復(fù)雜涂召,我們應(yīng)該怎么來(lái)處理果正?
這一點(diǎn)其實(shí)有很多的解決辦法,但是Redux-saga基本算是非常優(yōu)秀的解決辦法,嚴(yán)格貫徹了函數(shù)流式編程的思想,把一個(gè)復(fù)雜邏輯處理為一個(gè)數(shù)據(jù)流.
Redux-saga就是我們的救世主
redux-saga把我們上面的所有登錄的流程可以寫到一個(gè)工作流里面,香腸機(jī)器的組裝
//login.saga.js
import {loginReuest loginFetching,loginSuccess,loginError } from '../actions/login';
//請(qǐng)求登錄的數(shù)據(jù)流過(guò)程
export function* loginRequestFlow(submit_info) {
try {
yield put(loginFetching(isFetching:true))
const userInfoFromRemoteService = yield call(request,submit_info,'get');
yield put(loginSuccess(userInfoFromRemoteService));
const errorMessage = articleList.showapi_res_error;
if (errorMessage && errorMessage !== '') {
yield toastShort(errorMessage);
}
} catch (error) {
yield put(loginSuccess([]));
toastShort('網(wǎng)絡(luò)發(fā)生錯(cuò)誤舱卡,請(qǐng)重試');
}
}
export function* watchuserLoginRequest(sumbit_info) {
while (true) {
const {
sumbit_info
} = yield take(types.loginRequest);
yield fork(loginRequestFlow, );
}
}
//login.action.js
export function userLoginRequest(sumbit_info){
return {
types.loginRequest,
sumbit_info
}
}
Redux會(huì)監(jiān)視這個(gè)數(shù)據(jù)流的觸發(fā)
Redux saga 暴露了幾個(gè)方法矫钓,稱為 Effects赵辕,定義如下:
Fork
執(zhí)行一個(gè)非阻塞操作。
Take
暫停并等待action到達(dá)还惠。
Race
同步執(zhí)行多個(gè) effect蚕键,然后一旦有一個(gè)完成锣光,取消其他 effect铝耻。
Call
調(diào)用一個(gè)函數(shù)瓢捉,如果這個(gè)函數(shù)返回一個(gè) promise 泡态,那么它會(huì)阻塞 saga,直到promise成功被處理状答。
Put
觸發(fā)一個(gè)Action。
Select
啟動(dòng)一個(gè)選擇函數(shù)亮钦,從 state 中獲取數(shù)據(jù)充活。
takeLatest
意味著我們將執(zhí)行所有操作混卵,然后返回最后一個(gè)(the latest one)調(diào)用的結(jié)果幕随。如果我們觸發(fā)了多個(gè)時(shí)間,它只關(guān)注最后一個(gè)(the latest one)返回的結(jié)果睦霎。
takeEvery
會(huì)返回所有已出發(fā)的調(diào)用的結(jié)果走诞。
Redux-saga并沒有改變Redux對(duì)于state的處理,只不過(guò)借用了es6/es7的方法對(duì)一個(gè)相關(guān)流程的changeState函數(shù)進(jìn)行了包裝而已.
所以理解Redux-saga的工作原理,對(duì)于React和Redux工作原理理解是前提.