Redux中的重要概念


Action/Reducer/Store

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

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

Action和Action Creator

Action是一個對象,用來代表所有會引起狀態(state)變化的行為(例如服務端的響應,頁面上的用戶操作)。

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

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

Action對象是行為的描述,一般都會包含下面的信息:

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

Action通過Action創建函數(Action Creator)來創建,Action Creator是一個函數,最終返回一個Action對象。

對於添加任務這個行為,對應的Action Creator如下:

復制代碼
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有一個比較基本的認識。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM