我在學習redux的時候,一開始也以爲很難,不少東西很難以理解,由於我是先簡單學習了一遍Vue的,由於工做中用的都是react,因此Vue也忘得差很少了。寫這篇文章的緣由是想幫助想入門react的小夥伴們,同時也是對本身的一個技術小總結吧。前端
react難就難在它很自由,就提供了一個JSX,而後就沒有了。不過和當初React的定位也有關係,它並非一個框架,而是一個UI庫。而Vue纔是一個框架,由於不少事情它都幫你完成了,使用的時候僅須要知道相關的API。react
tips:能夠這麼粗淺的理解react,UI = fn(data)git
好了扯遠了,下面開始帶你入門redux吧。github
首先,在學習以前,要說明一點,react和redux沒有任何關係,沒有任何關係,沒有任何關係;重要的事情說三遍。那redux是什麼呢?是一個管理數據的倉庫。編程
緣由是由於前端數據的複雜度沒有人來管理,由於react當初的定位也是爲了解決中大型項目,項目一旦複雜起來,須要共享的數據就會很龐大複雜。redux
在介紹核心概念以前,咱們先來了解一個東西,就是Flux。在Flux中,Facebook最先提出了一個action的概念,經過action來直接修改數據倉庫store,action是一個普通的對象,用於描述要幹什麼。store根據不一樣的action來對數據進行操做。數組
這樣就會有一個問題,當業務複雜,數據龐大的時候,store的壓力就不少了,因此纔有了後面redux的出現,到這裏,你只須要知道redux的三個核心概念就能夠了。app
action:至關於頁面請求等操做,分發dispatch框架
store:數據的倉庫函數式編程
第一步:首先action是一個平面對象,就是一個簡單的對象,必需要傳type屬性,類型任意,表明着你要幹什麼,還有一個可選屬性是payload,就是請求時候的附加數據。
第二步:store接收到action的請求以後,把舊的數據state,和請求action交給reducer,讓reducer來修改數據,修改完以後返回一個新的數據newState給我,以便更新數據。
明白了上圖描述的redux工做流程以後,咱們須要建立一個store,由於根據上圖,不論是接收action,或者是觸發reducer修改數據,都是根據數據倉庫的,全部咱們先要建立一個數據倉庫。直接看下面代碼和註釋吧。
createStore 返回值是一個對象,對象包含如下幾個屬性
getState:獲得當前的state數據
Symbol('observable'):提案,暫時用不到
tips:到這裏,熟悉發佈訂閱模式的小夥伴,就知道其實 createStore 內部的代碼原理就是使用了發佈訂閱模式。不熟悉發佈訂閱模式的小夥伴須要去了解一下。
接着咱們把action和reducer完善好
最後咱們就可使用了,結合上圖的兩個步驟理解
tips:最好本身手動實現一遍代碼,而後按照redux工做原理兩大步驟圖理解一下。
根據上面redux的工做流程,有沒有發現太麻煩了?的確是太麻煩了,尤爲是第二步,要本身主動去使用store.dispatch,而後再往裏面塞action的平面對象。那有沒有方便一點的方法呢?redux提供了一個函數,bindActionCreators,加強action建立函數,讓action以後自動觸發dispatch。
使用起來就至關簡單了,下面作一個對比
如今還有一個問題,就是倉庫數據只有一個,只有一個reducer,而在實際的項目中,數據是很龐大的,有不少個reducer,那怎麼來管理這麼多數據呢?
咱們能夠先這樣解決問題
其實redux很貼心,爲我麼提供了至關於上面效果的一個函數,就是 combineReducers。
完善 validiteReducers 函數
使用的時候,只須要簡單的導出 combineReducers 的運行結果便可,由於它返回一個總的reducer函數,能夠對比一下不使用combineReducers的時候。
如今咱們基本上算是完成了一個簡陋版的redux,可是在實際的業務開發中,每每須要請求數據,打印日誌之類的不少附加功能,咱們就舉一個簡單的例子。如今有一個需求,我要打印舊數據和新數據。首先咱們分析一下需求,結合redux的工做流程,咱們知道,action必須返回一個沒有反作用的平面對象,reducer必須是一個純函數。何況action只能拿到舊數據,reducer也不行,觀察發現createStore裏面的能夠拿,那隻能在裏面作手腳了。怎麼作手腳呢?又不能影響原來的功能。
機智的咱們能夠先這樣作
其實這個就是middleware中間件的原理。並且,中間件如何運用在redux上?總不能像上面這麼low的寫法吧?別急,咱們一步步慢慢分析,理清楚下面這些概念
先看第五點,要使用中間件,必須調用applyMiddleware函數,將函數的返回值做爲createStore的第二或第三參數,來告訴倉庫,咱們建立倉庫的時候,要使用中間件。假設咱們有下面三個中間件,建立倉庫的時候調用applyMiddleware函數。applyMiddleware函數會倒着來運行每一箇中間件。在這裏你能夠先無論它爲何倒着來,先忽略。
而後用代碼來寫一遍,先書寫三個中間件。
而後使用中間件
到這裏,你可能會問applyMiddleware爲何要倒着來運行全部的中間件,這和代碼的運行邏輯有關,下面咱們就來解析一下applyMiddleware是怎麼來把全部的中間件運行起來的。在介紹applyMiddleware前,咱們先來認識一下compose,它是函數組合, 函數式編程中的聲明式編程,其實就是把全部的函數的功能組合到一塊兒。
其實能夠簡單的理解成,把全部函數的功能組合成一個函數,就是compose。
有了compose以後,咱們就能夠實現applyMiddleware的原理了,以下代碼
到這裏,咱們就知道爲何applyMiddleware一開始調用的時候是反過來的了。compose函數式編程的魔法,真香!!!
至此,三個中間件就會運用在建立函數裏面了,這也是爲何建立函數的第二個參數能夠傳中間件或者默認值,createStore的完整代碼應該是這樣的。
只看上面的代碼確定很羞澀難懂,結合下面的圖片看纔好理解
其實redux用applyMiddleware使用中間件就是一個洋蔥模型,用到切洋蔥(redux)的時候真想哭(學redux),吃洋蔥(react+redux)的時候,真香。
/**
那爲何要放在第一個呢?
tips:再仔細想下整個流程,最後跟着思路碼一邊。
前面咱們都是在講redux怎麼管理數據,那咱們的組件怎麼使用數據呢?
假設咱們都定義好了action、reducer,而且建立好了store。
那麼接下來咱們能夠這樣拿到數據(Users組件拿),直接定義兩個方法,把須要的數據映射進去。
仔細看mapStateToProps、mapDispatchToProps。咱們把須要的數據直接經過導入store,傳進去就完事了。同時訂閱一下this.setState就能夠完成改變數據就刷新界面的效果。
redux仍是很貼心的,哪裏麻煩就出哪裏的API,這時候就可使用react-redux中的 connect 方法了。首先你要理解下面的筆記,或者能夠直接去看相關的API文檔。
有了connect以後代碼就能夠變得很簡單了。直接導出就完事了
redux其實使用不難,可是理解原理,解析原理代碼是很是繞的,必定要多寫幾遍代碼理解才能真的學會使用redux。
這裏提供我學習redux源碼的全部代碼筆記,有興趣的小夥伴能夠clone下來研究學習。
github:github.com/huangruitia…