經過三張圖瞭解Redux中的重要概念

上週利用業餘的時間看了看Redux,剛開始有點不適應,一下在有了Action、Reducer、Store和Middleware這麼多新的概念。html

通過一些瞭解以後,發現Redux的單向數據裏的模式仍是比較容易理解的,結合着Redux的單向數據流模型,不少概念就比較清晰了。react

下面就按照本身的理解整理出了Redux中相關的內容,若是你也剛開始學習Redux,但願能給你一個直觀的認識。git

 

Action/Reducer/Store

首先,先看看第一張圖,圖中展現了Redux的單向數據流,以及Action、Reducer和Store這三個核心概念。github

下面就圍繞上圖,非別介紹Action、Reducer和Store這三個概念。redux

Action和Action Creator

Action是一個對象,用來表明全部會引發狀態(state)變化的行爲(例如服務端的響應,頁面上的用戶操做)。promise

假如咱們要實現一個任務管理系統,那麼添加任務的Action對象就會是下面的形式:app

{
    type: 'ADD_TASK',
    name: 'Read ES6 spec',
    category: 'Reading'
}

Action對象是行爲的描述,通常都會包含下面的信息:框架

  • 一個字符串類型的type字段來表示將要執行的動做
  • 須要傳遞給應用的其餘數據信息(例子中的name和category),數據形式用戶能夠自定義

Action經過Action建立函數(Action Creator)來建立,Action Creator是一個函數,最終返回一個Action對象。異步

對於添加任務這個行爲,對應的Action Creator以下:ide

function addTask(name, category) {
    return {
        type: ADD_TASK,
        name,
        category
    };
}

Reducer

Action對象僅僅是描述了行爲的相關信息,至於如何經過特定的行爲來更新state,就須要看看Reducer了。

關於Reducer,最簡單的描述就是:

  • Reducer是一個函數
  • 該函數接收兩個參數,一箇舊的狀態previousState和一個Action對象
  • 返回一個新的狀態newState

根據上面的描述,Reducer函數就能夠表示爲:

(previousState, action) => newState

Reducer函數的形式一般以下:

function reducer(state = [], action) {
    // 處理不一樣action的代碼
    switch (action.type) {
        case SPECIAL_ACTION:
            // 根據SPECIAL_ACTION action更新state
            // 返回新的state
        default:
            return state
    }
}

Store

Actions描述了"what happened"的事實,Reducers則根據這些actions來更新state,而Store則是Actions和Reducers鏈接在一塊兒的對象。

Store是Redux中數據的統一存儲,維護着state的全部內容,因此Store的主要功能就是:

  • 維護應用的state內容
  • 提供getState()方法獲取 state
  • 提供dispatch(action)方法更新 state
  • 提供subscribe(listener)方法註冊監聽器

看到Store提供的方法,就能夠把Action、Reducer和Store聯繫在一塊兒了:

  1. Store經過dispatch(action)方法來接收不一樣的Action
  2. 根據Action對象的type和數據信息,Store對象能夠經過Reducer函數來更新state的內容

 

Middleware

下面就來看看第二張圖,跟第一張圖的差異不大,只是增長了中間件(Middleware)來處理Action。

在Redux中,Middlerwares主要的做用就是處理Action,Redux中的Action必須是一個plain object。可是爲了實現異步的Action或其餘功能,這個Action可能就是一個函數,或者是一個promise對象。這是就須要中間件幫助來處理這種特殊的Action了。

也就是說,Redux中的Middleware會對特定類型action作必定的轉換,因此最後傳給reducer的action必定是標準的plain object。

針對Action的特徵,Reudx Middleware能夠採起不一樣的操做:

  • 能夠選擇傳遞給下一個中間件,如:next(action)
  • 能夠選擇跳過某些中間件,如:dispatch(action)
  • 或者更直接了當的結束傳遞,如:return。

Redux中經常使用的中間件:

  • redux-thunk:action能夠是一個函數,用來發起異步請求。
  • redux-promise:action能夠是一個promise對象,用來更優雅的進行異步操做。
  • redux-logger:action就是一個標準的plain object,用來記錄action和nextState的。

 

react-redux

通過前面的介紹,咱們已經看到了Redux中的一些核心概念。Redux跟React沒有直接的關係,自己能夠支持React、Angular、Ember等等框架。

經過react-redux這個庫,能夠方便的將react和redux結合起來:react負責頁面展示,redux負責維護/更新數據狀態。

到這裏,第三張圖就展現了react-redux這個庫的工做原理,react和redux是怎麼聯繫到一塊兒的。

react-redux中提供了兩個重要功能模塊Provider和connect,這兩個模塊保證了react和redux之間的通訊,下面就分別看看這兩個模塊。

Provider

經過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

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;
}        

 

詳細內容和demo

文中不少Redux的概念都是進行了簡單的介紹,更多詳細的介紹能夠參考我整理的內容,GitHub地址:WilberTian/StepByStep-Redux

每篇文章的結尾都會有一些簡單的demo 代碼,幫助理解文章中介紹的內容。

 

總結

文中結合三張圖片介紹了Redux中的一些核心概念,以及React和Redux之間經過react-redux這個庫進行交互。

更多詳細的內容,已經整理到了GitHub上了(WilberTian/StepByStep-Redux),經過這些介紹以及demo的運行結果,必定能對Redux有一個比較基本的認識。

全部的內容主要參考Usage with React,而後加上了本身的理解畫了上面三張圖,同時結合每一個概念寫了一些demo幫助理解。 

相關文章
相關標籤/搜索