天天看點

《ReactNative實戰系列》Redux架構篇---(一)基礎知識

| 版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。

Redux架構篇系列文章總目錄:

《ReactNative實戰講義》Redux架構篇—(一)基礎知識

《ReactNative實戰講義》Redux架構篇—(二)基礎應用

《ReactNative實戰講義》Redux架構篇—(三)進階知識

《ReactNative實戰講義》Redux架構篇—(四)進階應用

一、簡介

今天給大家介紹一個新的架構—Redux,這個架構在項目中的位置很重要,基本可以算作項目基礎架構的核心。在以後的項目中我們會圍繞Redux架構打造一個架構群,是以Redux架構戰略地位很重要,當然了解起來還是有相當程度的難度,本篇文章為大家介紹一些關于Redux的基礎概念,我會通過一系列的文章帶大家認識Redux,了解Redux,使用Redux,首先我們先來看看Redux是個什麼東東。

二、Redux被創造出來的目的是什麼?

無論是做過React開發,還是ReactNative開發的小夥伴應該都清楚在開發的過程中每個頁面中或多或少都會出現狀态(State),這是React的基礎元素。随着項目不斷的疊代,功能不斷地增加,複雜程度不斷地提高,有越來越多的State值需要我們去管理,複雜的會遇到多頁面共用一個狀态值,反過來說,一個狀态值會影響多個頁面的顯示。這時,對于狀态的管理要求就更高了。而Redux的出現就是為了解決這一問題。

講到這裡我們知道了Redux的出現和項目的State有關,那麼它能做到什麼呢?

将所有的State變化進行統一流程的處理,會使我們的程式狀态變化清晰可變。Redux的最終目的就是讓狀态變化變得可預測。

三、核心理念

  • Redux将應用的state狀态集中管理;
  • 唯一能夠修改狀态的方法是通過發起action動作的方式修改;
  • 通過reducer将state和action連接配接起來,根據action的類型建立相應新的state;
  • React根據新的State修改UI;

以上幾點串聯起來就是Redux架構工作的流程,這隻是籠統的概括,細節的地方我們後面會講到。

四、基礎元素

Redux架構使用時的三大元素

1. Action

  • 類型:普通JS對象
  • 參數:type字段,表示要執行的動作,多數情況下會被定義成字元串常量
  • 代碼示例:
  • 深度解釋:state隻讀,唯一修改state的方式是發起action動作,action動作實質上是個普通對象,正因為他包含了動作類型(type),需要修改的資料内容(比如,id,data…)。記住,action隻是描述有事情發生了并且攜帶了相關資料元素。他并不會描述應用如何更新state。
  • 代碼示例:
// 定義區分動作類型的常量
const LOAD_LIST = 'LOAD_LIST';
// 不成文的規定第一個參數我們設定成type,後面表示發起Action的類型
// 比如:LOAD_LIST 加載清單内容,response後面所帶内容為需要加載的清單資料
// 原則上這個普通的JS對象裡面的參數都是可以自定義的,根據項目實際需求來定。
{ type: 'LOAD_LIST', response: { ... } }

// 實戰中建立ActionCreater的标準樣式
export const getList = (listData) => {
    return { type: 'LOAD_LIST', response: listData } 
}
           

2. Reducer

  • 類型:純函數
  • 作用:将action和state結合在一起。接受Action,根據Action中所承載的object資料,建立新的state并傳回。
  • 任務:reducer要完成的任務僅僅是接受action和舊的state,傳回新的state
  • 禁止:修改傳入的參數,執行副作用的操作(API請求和路由跳轉),調用非純函數(如:Data.now()和Math.random())
  • 傳回值:傳回值相當于舊的state在末尾加上建立的state。而這個新的state又是基于action中攜帶的資料建立的。
  • 代碼示例:
// 初始化的State值
let initialList = { list: [] }

// 前面講到了Action就是一個普通的JS對象,裡面包含了自定義的參數。
export const listData = (state = initialList, action) => {
    switch(action.type) {
        case: 'LOAD_LIST':
            return {
                ...state,
                list: action.response
            }

        return state;
    }   
}
           

3. Store

  • 作用:将action和reducers聯系在一起
  • 功能:維持存儲應用的state
  • API:
  • getState()方法擷取state
  • dispatch(action)方法更新state
  • subscribe(listener)注冊監聽器
  • subscribe(listener)傳回的函數登出監聽器
  • 特點:全局隻有一個單一的store
  • 代碼示例
import { createStore } from 'redux';
import { listData } from './reducers';
import { getList } from './actions';
let store = createStore(listData);

// 列印初始狀态
console.log(store.getState());
// 每次state更新時,列印日志
// 注意subscribe()傳回一個函數用來登出監聽器
const unsubscribe = store.subscribe(
    () => console.log(store.getState())
);
// 監聽一系列action
store.dispatch(getList(
[
    {id: , name: 'bob'}, 
    {id: , name: 'fsf'}
]));
// 停止監聽state更新
unsubscribe();
           

注:關于Store做了些什麼工作,我們後續講解。

4. 架構特性(設計核心)

嚴格的單向資料流

下面我們整體串聯一下Redux架構每個使用步驟,從中體會一下資料流單向流動的特點。

1. 使用者觸發按鈕或者其他動作,調用store.dispatch(action);

  • Action就是一個描述了“發生了什麼”的普通對象,同時也是資料的載體。

示例代碼:

{ type: 'LIKE_ARTICLE', articleId: }
{ type: 'FETCH_USER_SUCCESS', response: { id: , name: 'bob' } }
{ type: 'ADD_TODO', text: 'Read the Redux docs' }
           

2. Redux store 調用傳入的reducer函數

  • Store會把兩個參數傳入reducer:目前的state樹和action。

内部代碼示例

// 目前應用的 state(todos 清單和選中的過濾器)
 let previousState = {
   visibleTodoFilter: 'SHOW_ALL',
   todos: [
     {
       text: 'Read the docs.',
       complete: false
     }
   ]
 }

 // 将要執行的 action(添加一個 todo)
 let action = {
   type: 'ADD_TODO',
   text: 'Understand the flow.'
 }

 // reducer 傳回處理後的應用狀态
 let nextState = todoApp(previousState, action);
           
  • reducer是純函數,它僅僅用于計算下一個state,即多次傳入相同的輸入必須産生相同的輸出。它不應該有副作用的操作,如API調用或路由跳轉,這些應該在dispatch action前發生。

3. 根reducer應該把多個子reducer輸出合并成一個單一的state樹。

  • 根reducer的結構完全由你決定,Redux原生提供combineReducers()輔助函數,來把根reducer拆分成多個函數,用于分别處理state樹的一個分支。
// 以下代碼示範了combineReducers()函數的使用方法
function todos(state = [], action) {
   // 省略處理邏輯...
   return nextState;
 }

 function visibleTodoFilter(state = 'SHOW_ALL', action) {
   // 省略處理邏輯...
   return nextState;
 }

 let todoApp = combineReducers({
   todos,
   visibleTodoFilter
 })
           
  • 當你觸發action時,combineReducers()傳回的todoApp會負責調用兩個reducer
let nextTodos = todos(state.todos, action);
let nextVisibleTodoFilter = visibleTodoFilter(state.visibleTodoFilter, action);
           
  • 然後會把兩個結果集合并成一個state樹:
return {
   todos: nextTodos,
   visibleTodoFilter: nextVisibleTodoFilter
 };
           

4. Redux store 儲存了根reducer傳回的完整state樹

  • 這個新的樹就是應用的下一個state!所有訂閱store.subscribe(listener)的監聽器都将被調用;監聽器裡可以調用store.getState()擷取目前state,最後根據新的state更改UI。
  • 小結:以上就是Redux架構的核心工作流程,其中也蘊含着Redux的設計理念。