實例講解Redux

實例講解Redux

示例代碼地址在這裏 ,你能夠經過git clone命令clone到本地,也能夠直接下載。javascript

而後經過執行npm install 安裝所依賴的模塊 。以後即可以經過node 執行示例代碼。java

什麼是Redux

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

簡單來講Redux就是javaScript 的狀態管理器。同時,Redux支持ReactAngularEmberjQuery等。ios

到這裏你可能並不知道該如何使用Redux,彆着急,在瞭解如何使用以前,須要先理解相關的基本概念。示例代碼可查看demo1/app.jsgit

State

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

Action

Action就是你與界面進行交互的行爲。它是一個對象且必需要包含一個type屬性,用來描述你要作的是什麼事。github

Store

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

Reducer

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

Talk is cheap, Show me the code!

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

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,它接受了當前stateaction參數。用來更新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。是因爲typeIOS,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_iosaction_webaction_snack,並將建立Action的任務交給這三個函數。

與此同時在咱們demo2/app.js中須要dispatch一個action的時候。只須要從Action creator中取出Action就好了。並不須要咱們手動的去建立,如此一來便大大增長代碼的可讀性,可維護性。

分散Reducer

一樣的隨着業務量的增長,Reducer一定也會愈來愈大。因此咱們能夠按模塊的不一樣來拆分Reducer。將一個大的Reducer拆分紅幾個小的reducer

demo3reducer文件夾中,咱們按照模塊的不一樣的拆分homeReducerprofileReducer。分別用來處理home頁面和profile頁面狀態的更新。

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

彆着急,在redux中提供了一個combineReducers的方法,用來組合咱們的Reducer

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

最後

謝謝閱讀,若是感受本文對你有用,那將是個人榮幸。若是有寫的錯誤的地方也請留言指正。

相關文章
相關標籤/搜索