數據流 in redux

前不久用react和react-router寫了個單頁面應用,但寫完後總感受還欠缺點什麼,組件間的狀態和數據相對較爲獨立,並且兄弟組件間的通訊很不方便。而後才瞭解到,在react應用中,能夠存在一個負責整合數據流向的框架,因而就選擇了redux.react

根據個人理解下面說一下redux的思想:git

redux由三個部分組成,即store,reducer以及action,直觀一點,你能夠把store理解爲數據庫,reducer是事件處理函數,action是觸發事件。爲何能夠這麼理解呢,由於整個redux的大體邏輯是這樣的:github

1 dispatch(action),即觸發action,(事件發生)數據庫

2 reducer根據當前所觸發action執行相對應的函數,更新state,(執行事件處理函數,更新數據庫數據)redux

3 store的state會爲應用所獲取,像數據庫同樣react-router

固然可能並非那麼契合,但大體的能夠這麼理解。如今咱們再仔細的看一看redux的數據流。app

1 dispatch的action會被reducer捕獲到,實際上是action先被傳送至store,再由store交付給reducer的,由於dispatch是store的方法,action經過回調到達的store,而以前咱們在建立store的時候使用了這樣的聲明 var store = createStore(reducer),使得store與reducer創建了某種聯繫,天然的,reducer可以接收到觸發的action。框架

2 上面是redux內部數據流的實現,可是redux與應用之間的數據流動是怎麼創建起來的呢?由於通常來講,是由應用的視圖觸發action,而後redux的reducer根據接收到的action執行相應的處理函數更新store的state,而state又是做爲數據來源與應用綁定的,因此store的state一更新,應用視圖也會同步刷新。因此這裏的問題是,應用是如何得到dispatch action的能力以及來自store的數據的呢?這個就須要藉助react-redux的Provider以及connect組件了。異步

經過Provider組件爲應用組件再加一層外殼,並傳入整個應用的store。async

 
connect組件負責連接store與應用。其中select函數會接收到來自store的state,在這裏能夠對state進行相應的預處理再返回應用所需state,state會連同store的dispatch方法以屬性方式傳入App組件即應用組件。
 
 

todo項目,說明整個項目的核心思想

redux的數據流思想大體如此,但這只是我本身的理解,可能會有所紕漏。

看了redux官方文檔以後,照着葫蘆畫瓢也實現了一個todo小應用。


 

整個應用的編寫思路其實不外乎上面所談及的那些。

可是須要注意的是,上面截圖中的第一條todo實際上是經過異步添加上去的,然而dispatch只能觸發同步的action,即傳遞普通的action對象,由於這樣咱們的action才能被reducer所接收到並觸發相對應的處理函數。因此,若是須要觸發異步的action的話,常規的方法是不行了的,咱們須要使用點小技巧。這裏又涉及到redux中間件(middleware)的概念了。簡單介紹下,所謂中間件,就是在action被觸發以及還沒被reducer接收到之間這段時間所執行的一段函數,其內部封裝有dispatch方法。中間件的存在是dispatch擴展的惟一標準方式。

咱們想要使用中間件的話,須要藉助applyMiddleware方法,它可以使中間件與store創建某種聯繫,使得store的dispatch和getState方法傳入中間件。

說回咱們以前所說的異步action,異步請求的實現咱們能夠藉助於redux-thunk中間件,這個中間件會去攔截異步action,由於通常狀況下異步action是action建立函數所返回的一個函數,因此redux-thunk中間件會替咱們去執行這個函數。執行的最後,通常會dispatch普通的action對象,reducer捕獲到此action對象,作出相應。

這是咱們的異步action建立函數,會返回一個異步函數

//異步action
export function asyncAction(){
    return function(dispatch, getState){
        setTimeout(function(){
            dispatch(addTodo("2秒鐘過去啦!你還沒添加新的任務,我來幫你添加一個吧!"))
        },2000)
    }
};

而後咱們dispatch它

dispatch(asyncAction());

由於返回的是異步action對象(函數),會被redux-thunk攔截並執行,執行的最後dispatch一個普通的action事件,成功添加一條todo。

完整的代碼在這裏 https://github.com/JerelLin/redux-todo

 

睡覺

相關文章
相關標籤/搜索