實例講解Redux

pseudo1234 8年前發布 | 17K 次閱讀 Redux JavaScript開發 JavaScript

什么是Redux

隨著 JavaScript 單頁應用開發日趨復雜, JavaScript 需要管理比任何時候都要多的 state (狀態) 。 這些 state 可能包括服務器響應、緩存數據、本地生成尚未持久化到服務器的數據,也包括 UI 狀態,如激活的路由,被選中的標簽,是否顯示加載動效或者分頁器等等。

簡單來說 Redux 就是 javaScript 的狀態管理器。同時, Redux 支持 React 、 Angular 、 Ember 、 jQuery 等。

到這里你可能并不知道該如何使用 Redux ,別著急,在了解如何使用之前,需要先理解相關的基本概念。示例代碼可查看 demo1/app.js

State

在一個可以進行用戶交互的界面上,當我們觸發了交互事件的時候,界面也會跟著進行更新。例如在一個app中的下拉刷新,當我們進行下拉刷新這個動作時,會去請求服務器數據,當返回結果時app的頁面會更新。界面的改變我們就可以看做是狀態的變化。而狀態的變化是由于我們進行了某個動作。在Redux中,尤其需要注意的是 State是只讀的 ,且狀態的變化只能通過Reducer函數進行轉換,

Action

Action就是你與界面進行交互的行為。它是一個對象且 必須要包含一個 type 屬性 ,用來描述你要做的是什么事。

Store

Store 就是應用狀態的容器。用來維護應用的 state 、獲取 state 、更新 state 、監聽 state 變化等。這里需要注意的是 整個應用只有一個 Store

Reducer

一個純函數,接收當前的 state 和一個 action 參數,根據當前的行為,即 action 的 type 屬性返回一個新的 state 。狀態的更新只能通過這個函數。

Talk is cheap, Show me the code!

可能看了上述內容你仍然不知道什么是 Redux , Redux 能干什么 。下面結合實例 demo1/app.js 中的內容理解上述概念。

1.引入相關模塊(這里沒有使用 ES6 的方式是為了能使用 node 命令直接查看結果, node 命令無法識別 import 。當然你也可以通過配置 babel 的方式使用 import 語法)

var { createStore } = require('redux');
//import { createStore } from 'redux' //es6方式引入

2.定義 Reducer ,來進行狀態的更新

var defaultState = 'JavaScript'
function programLanguage(state = defaultState, action) {
    switch (action.type) {
        case 'IOS':
            return action.language;
        case 'WEB':
            return action.language;
        case 'SNACK':
            return action.language;
        default:
            return state;
    }
}

從上述代碼可以看到,我們定義了一個 programLanguage 方法,其實這就是一個 Reducer ,它接受了當前 state 和 action 參數。用來更新 state 。

3.創建 store 。

let store = createStore(programLanguage);

再次強調整個應用中只能有一個 store ,即 createStore 函數只能被調用一次。

createStore 的定義如下:

function createStore(reducer, preloadedState, enhancer);

可以看到的是createStore接受三個參數

  • reducer:就是上述的reducer函數,這里不再贅述

  • preloadedState: 初始state

  • enhancer:組合store creator的高級函數,返回一個新的強化過的store creator。

4.更改應用的狀態

store.dispatch({ type: 'default' });
store.dispatch({ language: 'Swift', type: 'IOS' });
store.dispatch({ language: 'Ruby', type: 'WEB' });
store.dispatch({ language: 'Python', type: 'SNACK' });

通過 dispatch 方法將 action 發送到 reducer 函數中,進行狀態的更新。

執行 node demo1/app.js 的打印結果如下

JavaScript
JavaScript Swift
JavaScript Swift Ruby
JavaScript Swift Ruby Python

當執行第一句代碼 store.dispatch({ type: 'default' }); 時 返回的是JavaScript。是由于dispatch方法內部會調用在 createStore 中注冊的 Reducer 函數,即 programLanguage 函數。由 programLanguage 的內部邏輯 return 的是一個 defaultState 。此時整個應用的狀態為 JavaScript

當執行第二句代碼 store.dispatch({ language: 'Swift', type: 'IOS' }); 時 返回了 JavaScript Swift 。是由于 type 為 IOS , programLanguage 返回的是 state + ' ' +action.language; 因為上一句代碼將應用的狀態變為了 JavaScript ,所以結果自然就是 JavaScript Swift 。同時整個應用的狀態也會變成 JavaScript Swift 。

同理,第三句和第四句代碼也是如此。

5.訂閱狀態的更新

store.subscribe(() =>
    console.log(store.getState())
);

為了方便查看狀態的變化。這里調用了 subscribe 方法,每當狀態發生變化時都會調用其回調函數。

store.getState() 獲取應用的當前狀態。

優化操作

Action creator

隨著頁面的增加, Action 必然也會越來越多,如果 Action 內部所攜帶的消息也很多。此時如果需要狀態的更新,就需要寫復雜的 Action ,造成代碼可讀性差,文件臃腫。所以我們可以使用 Action creator 來構造 Action 。當需要進行狀態更新就傳入相應的數據到 Action creator 中生成 Action 并返回。

在 demo2 中

我們創建了一個 HomeAction 的文件專門用來存放 Action Creator 。在此文件中我們創建了三個 Action creator ,分別是 action_ios 、 action_web 、 action_snack ,并將創建 Action 的任務交給這三個函數。

與此同時在我們 demo2/app.js 中需要 dispatch 一個 action 的時候。只需要從 Action creator 中取出 Action 就行了。并不需要我們手動的去創建,如此一來便大大增加代碼的可讀性,可維護性。

分散Reducer

同樣的隨著業務量的增加, Reducer 必定也會越來越大。所以我們可以按模塊的不同來拆分Reducer。將一個大的 Reducer 拆分成幾個小的 reducer 。

在 demo3 中 reducer 文件夾中,我們按照模塊的不同的拆分 homeReducer 和 profileReducer 。分別用來處理 home 頁面和 profile 頁面狀態的更新。

那么問題來了,這么拆分如何使用 createStore 去創建 store 呢,畢竟 createStore 只能傳一個 Reducer 參數。而且 createStore 只能調用一次。

別著急,在 redux 中提供了一個 combineReducers 的方法,用來組合我們的 Reducer 。

const mainReducer = combineReducers({
    homeReducer,
    profileReducer
})
let store = createStore(mainReducer);

 

來自:https://segmentfault.com/a/1190000007515109

 

 本文由用戶 pseudo1234 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!