前不久用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
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
睡覺