上週利用業餘的時間看了看Redux,剛開始有點不適應,一下在有了Action、Reducer、Store和Middleware這麼多新的概念。html
通過一些瞭解以後,發現Redux的單向數據裏的模式仍是比較容易理解的,結合着Redux的單向數據流模型,不少概念就比較清晰了。react
下面就按照本身的理解整理出了Redux中相關的內容,若是你也剛開始學習Redux,但願能給你一個直觀的認識。git
首先,先看看第一張圖,圖中展現了Redux的單向數據流,以及Action、Reducer和Store這三個核心概念。github
下面就圍繞上圖,非別介紹Action、Reducer和Store這三個概念。redux
Action是一個對象,用來表明全部會引發狀態(state)變化的行爲(例如服務端的響應,頁面上的用戶操做)。promise
假如咱們要實現一個任務管理系統,那麼添加任務的Action對象就會是下面的形式:app
{ type: 'ADD_TASK', name: 'Read ES6 spec', category: 'Reading' }
Action對象是行爲的描述,通常都會包含下面的信息:框架
Action經過Action建立函數(Action Creator)來建立,Action Creator是一個函數,最終返回一個Action對象。異步
對於添加任務這個行爲,對應的Action Creator以下:ide
function addTask(name, category) { return { type: ADD_TASK, name, category }; }
Action對象僅僅是描述了行爲的相關信息,至於如何經過特定的行爲來更新state,就須要看看Reducer了。
關於Reducer,最簡單的描述就是:
根據上面的描述,Reducer函數就能夠表示爲:
(previousState, action) => newState
Reducer函數的形式一般以下:
function reducer(state = [], action) { // 處理不一樣action的代碼 switch (action.type) { case SPECIAL_ACTION: // 根據SPECIAL_ACTION action更新state // 返回新的state default: return state } }
Actions描述了"what happened"的事實,Reducers則根據這些actions來更新state,而Store則是Actions和Reducers鏈接在一塊兒的對象。
Store是Redux中數據的統一存儲,維護着state的全部內容,因此Store的主要功能就是:
看到Store提供的方法,就能夠把Action、Reducer和Store聯繫在一塊兒了:
下面就來看看第二張圖,跟第一張圖的差異不大,只是增長了中間件(Middleware)來處理Action。
在Redux中,Middlerwares主要的做用就是處理Action,Redux中的Action必須是一個plain object。可是爲了實現異步的Action或其餘功能,這個Action可能就是一個函數,或者是一個promise對象。這是就須要中間件幫助來處理這種特殊的Action了。
也就是說,Redux中的Middleware會對特定類型action作必定的轉換,因此最後傳給reducer的action必定是標準的plain object。
針對Action的特徵,Reudx Middleware能夠採起不一樣的操做:
Redux中經常使用的中間件:
通過前面的介紹,咱們已經看到了Redux中的一些核心概念。Redux跟React沒有直接的關係,自己能夠支持React、Angular、Ember等等框架。
經過react-redux這個庫,能夠方便的將react和redux結合起來:react負責頁面展示,redux負責維護/更新數據狀態。
到這裏,第三張圖就展現了react-redux這個庫的工做原理,react和redux是怎麼聯繫到一塊兒的。
react-redux中提供了兩個重要功能模塊Provider和connect,這兩個模塊保證了react和redux之間的通訊,下面就分別看看這兩個模塊。
經過Provider的代碼能夠看到,Provide本質上是一個react組件。
export default class Provider extends Component { getChildContext() { return { store: this.store } } constructor(props, context) { super(props, context) this.store = props.store } render() { const { children } = this.props return Children.only(children) } }
Provider組件主要用到了react經過context屬性,能夠將屬性(props)直接給子孫component,無須經過props層層傳遞,從而減小組件的依賴關係。
connect方法的主要做用就是讓Component與Store進行關聯, Store的數據變化能夠及時通知Views從新渲染。
任何一個經過connect()函數處理過的組件均可以獲得一個dispatch方法做爲組件的props,以及獲得全局state中的全部內容。
經過源碼]能夠看到,connect函數運行後,會返回一個wrapWithConnect函數,該函數能夠接收一個react組件,而後返回一個通過處理的Connect組件。
return function wrapWithConnect(WrappedComponent) { class Connect extends Component { constructor(props, context) { // 從祖先Component處得到store this.store = props.store || context.store this.stateProps = computeStateProps(this.store, props) this.dispatchProps = computeDispatchProps(this.store, props) this.state = { storeState: null } // 對stateProps、dispatchProps、parentProps進行合併 this.updateState() } shouldComponentUpdate(nextProps, nextState) { // 進行判斷,當數據發生改變時,Component從新渲染 if (propsChanged || mapStateProducedChange || dispatchPropsChanged) { this.updateState(nextProps) return true } } componentDidMount() { // 改變Component的state this.store.subscribe(() = { this.setState({ storeState: this.store.getState() }) }) } render() { // 生成包裹組件Connect return ( <WrappedComponent {...this.nextState} /> ) } } Connect.contextTypes = { store: storeShape } return Connect; }
文中不少Redux的概念都是進行了簡單的介紹,更多詳細的介紹能夠參考我整理的內容,GitHub地址:WilberTian/StepByStep-Redux
每篇文章的結尾都會有一些簡單的demo 代碼,幫助理解文章中介紹的內容。
文中結合三張圖片介紹了Redux中的一些核心概念,以及React和Redux之間經過react-redux這個庫進行交互。
更多詳細的內容,已經整理到了GitHub上了(WilberTian/StepByStep-Redux),經過這些介紹以及demo的運行結果,必定能對Redux有一個比較基本的認識。
全部的內容主要參考Usage with React,而後加上了本身的理解畫了上面三張圖,同時結合每一個概念寫了一些demo幫助理解。