關于Redux為核心的應用開發簡介


title: 關于Redux為核心的應用開發簡介
date: 2017-04-20 08:05:04
categories: React-native
tags: Redux


問題出發點,當我們在UI組件中執行交互操作(點擊,滑動,提交),我們要考慮到怎么來響應操作.函數式編程里有個圖,有一個機器,從一邊放入肉,另一邊出火腿.這就是一個流程.application的操作其實就是解決點擊=>結果展示的流程.
但是實際流程中需要解決的問題很多.我們要考慮怎么來更好的管理application 的狀態問題. 具備javascript的基礎知識,幾個模式設計的東西,函數式編程的知識,React的知識,Redux的思想.可以說想在實際應用中玩轉React/Redux/Redux-saga/immutable。需要掌握的東西還是很多的.
我先寫一點具體的一些學習內容和需要的思想.

輔助觀念轉變的一個生活實例

先看個電燈電路

電燈的原理圖
電燈的原理圖
  1. 控制開關執行動作(操作),
  2. 電燈根據開關的動作來改變狀態,
  3. 電燈的狀態不是由自己決定的,電路里有電了就會亮,沒電了就不亮,像木偶一樣受到控制.

飛機座艙

早期的座艙
早期的座艙

各個儀表都和自己的傳感器連接在一起,加上冗余備份的儀表,很難設計和維護

先進座艙
先進座艙

80-90年代的window操作系統(不止windows奧),起源其實就是早期美國國防部的科研項目.
傳感器和顯示屏就沒有那么多線了.由數據總線來做集中統一處理.

理解React/Redux/Redux-saga架構的基礎知識

函數式編程思想

函數式編程想的模擬香腸機器
函數式編程想的模擬香腸機器

函數式編程把流程拆為幾個有聯系的步驟,可以分解流程,易于維護.合起來完成一個具體的任務.
但是這只是函數式編程的一個組成部分
在javascript的函數式編程中用到很多概念

  1. 函數作為一類對象,可以作為數組的元素,可以作為函數的參數來傳遞.
  2. 基于流的編程(redux-saga就是基于流的編程).
    基于流的編程
    基于流的編程
  3. 閉包的概念


    閉包的概念圖
    閉包的概念圖
一個簡單的閉包函數
一個簡單的閉包函數

作為工具函數的閉包
作為工具函數的閉包
  1. high-order function 接受其他函數作為參數的函數
  2. 純函數,對象的immutable,狀態改變.

一個實際的流程分析

在用戶提交表單的時候,我們想要做如下事情:

1. 校驗一些輸入信息 (簡單, 寫在組件里)
Validate方法,可以考慮導入redux-form組件,自帶驗證方法
2. 驗證以后可以讓提交按鈕改為可以提交狀態了
```
//login.UI.js登錄組件
this.props.dispatch(userLoginRequest(submit_info));
//已經結束了,不要想太多,用戶和組件的交互就是表單輸入和提交按鈕
//所以這里也執行這個過程就可以了.

 ```

3. 彈起提示信息(React組件化的優勢,公共組件)

```
   //login.Ui.js
  //Lodaing組件
 this.props.isFetching?<Loading>:null
 
```

4. 提交后端服務 (我們用fetch,這個是不變的,redux只是對流程的控制,并不是要改變實際做事的方法)

5. 拿到后端返回狀態 (promise resolve)
6. 隱藏提示信息 (鴻門宴啊,摔杯為號,這不就是狀態嗎?)

 ```
   //login.UI.js
   this.props.isFetching?<Loading>:null
 
  ``` 

7. 更新redux store (reducer的操作)

  //login.reducer.js
  
  return state.merge(resolve.result);
  

8. 登錄界面的任務完成了.根據業務需要跳轉到對應的頁面

  //reducer.js
  
  return state.merge(resolve.result);
  
  //login.js
  
  this.props.loginsuccess?(Action.Mycenter):(Action.refresh)
  

這里我們就把登錄的流程做了分解.好處是很多的,流程都是根據狀態來的變化的,
代碼書寫清晰,在每一步的dubug和測試過程都很容易,因為我們可以獲取每一步的狀態

由于有redux-logger的中間件存在,我們還可以查看每一步的狀態變化.好像還有圖形化的界面來顯示state的變化.

總的原則是React組件只負責信息展示,簡單的驗證
復雜的邏輯現在全部在Redux中來實現

副作用(side effect)到底是個什么?

副作用其實就可以理解為由外部API提供的服務.這個服務和我們的app的流程是沒有關系的,我們只需要給接口提供參數,等待接口返回數據就可以了.

React/Redux/Redux-saga

React的概念,原理

  1. React內心是虛擬DOM,在react中的html代碼實際是React渲染的模板


    react組件中的html代碼叫jsx代碼,不是實際的html代碼,是js代碼
    react組件中的html代碼叫jsx代碼,不是實際的html代碼,是js代碼
  2. React渲染動態內容的方式通過外部父組件傳入的props和組件內部的state來實現
    絕對不可以搞錯的概念:組件之間要傳遞參數只能通過props來實現,state只能在組件內部使用,如果要把sate傳遞到其他組件,一定要經過轉換
    在React中,props和state都有兩類不同的id來區分,不同的id類型是找不到對方的內容的.Redux的mapStateToProps方法就是把State的類型id轉為props的類型id.
    由此可以得出什么結論呢?

其實Redux也是一個React的組件.

Redux的mapStateToProps函數的主要目的是什么?
Redux的mapStateToProps函數的主要目的是什么?

******切記,切記*******

3.Connect這個函數是非常重要的函數
組件要訂閱state的變化,能夠訂閱dispatch的方法都是通過connect函數來執行的.

Redux的出現

Redux的流程圖
Redux的流程圖

Redux負責把React的邏輯處理獨立出來處理
Redux的要點有:

  1. 一個應用只有一個state
  2. state是只讀的,這是immutable的概念.
  3. 修改state只能是用純函數來執行,dispatch(Action(params))

一旦React的應用中加入Redux的構架以后,所有Appliction的核心就由組件轉變到Redux中了.如果和傳統的web的 browser/server來類比,Redux就變成了服務器的角色,state就承擔了數據庫的角色.

組件之前的state的改變現在要重新思考了.

Redux承擔了服務器和數據庫的角色
Redux承擔了服務器和數據庫的角色

組件之間就最好再也不要做數據的傳遞,組件要執行渲染的sate統一從Redux的store中獲取.
這一步思考方法的改變是極為重要的.

如果一個流程的過程非常的復雜,我們應該怎么來處理?

這一點其實有很多的解決辦法,但是Redux-saga基本算是非常優秀的解決辦法,嚴格貫徹了函數流式編程的思想,把一個復雜邏輯處理為一個數據流.

Redux-saga就是我們的救世主

redux-saga把我們上面的所有登錄的流程可以寫到一個工作流里面,香腸機器的組裝

 //login.saga.js
 import {loginReuest loginFetching,loginSuccess,loginError } from '../actions/login';
 //請求登錄的數據流過程
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('網絡發生錯誤,請重試');
  }
}

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-saga把登錄的流程變為一個函數流操作,所有有關的操作都在這里面實現
Redux-saga把登錄的流程變為一個函數流操作,所有有關的操作都在這里面實現

Redux會監視這個數據流的觸發

Redux-saga通過監控特定的ActionType來觸發操作
Redux-saga通過監控特定的ActionType來觸發操作

Redux saga 暴露了幾個方法,稱為 Effects,定義如下:

Fork 執行一個非阻塞操作。

Take 暫停并等待action到達。

Race 同步執行多個 effect,然后一旦有一個完成,取消其他 effect。

Call 調用一個函數,如果這個函數返回一個 promise ,那么它會阻塞 saga,直到promise成功被處理。

Put 觸發一個Action。

Select 啟動一個選擇函數,從 state 中獲取數據。

takeLatest 意味著我們將執行所有操作,然后返回最后一個(the latest one)調用的結果。如果我們觸發了多個時間,它只關注最后一個(the latest one)返回的結果。

takeEvery會返回所有已出發的調用的結果。

Redux-saga并沒有改變Redux對于state的處理,只不過借用了es6/es7的方法對一個相關流程的changeState函數進行了包裝而已.

所以理解Redux-saga的工作原理,對于React和Redux工作原理理解是前提.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容