Dva 5分鐘上手指南

該篇文章適合的閱讀人羣:剛接手公司項目,技術棧爲react,狀態管理直接用的dva,可是不太瞭解redux、redux-saga、react-redux的人員,想要快速上手業務開發,看這篇就對了!

1. Dva是什麼?

dva 首先是一個基於 redux 和 redux-saga 的數據流方案,而後爲了簡化開發體驗,dva 還額外內置了 react-router 和 fetch,因此也能夠理解爲一個輕量級的應用框架。javascript

2. 快速上手開發?(保存用戶信息爲例)

  • 定義Model文件用於全局的用戶信息數據管理,以下代碼:
// 引入接口方法用於在effects中編寫所需的業務邏輯
import { queryCurrent } from '@/services/user'

// 實際上只是按規則定義一個配置對象
const UserModel = {
  // 當前 Model 的名稱。整個應用的 State,由多個小的 Model 的 State 以 namespace 爲 key 合成
  namespace: 'user',
  // 該 Model 當前的狀態。數據保存在這裏,直接決定了視圖層的輸出
  state: {
    currentUser: {}
  },
  // Action 處理器,處理異步動做,基於 Redux-saga 實現。Effect 指的是反作用。根據函數式編程,計算之外的操做都屬於 Effect,典型的就是 I/O 操做、數據庫讀寫。
  effects: {
    // Effect 是一個 Generator 函數,內部使用 yield 關鍵字,標識每一步的操做(無論是異步或同步)。
    *fetchCurrentUser({ payload, callback }, { call, put }) {
      // 執行異步函數
      const response = yield call(queryCurrent)
      if(response.success) {
        const { user } = response
        if(callback) {
          callback(user)
        }
        // 發出一個 Action,相似於 dispatch
        yield put({
          type: 'saveCurrentUser',
          payload: user
        })
      }
    }
  },
  // Reducer 是 Action 處理器,用來處理同步操做,能夠看作是 state 的計算器。它的做用是根據 Action,從上一個 State 算出當前 State。
  reducers: {
    saveCurrentUser(state, { payload = {} }) {
      return {
        ...state,
        currentUser: payload
      }
    }
  }

}

export default UserModel;
  • 使用connect鏈接上Dva並使用,以下代碼:
import { connect } from 'dva'

const SetUserInfoComponent = props => {
  const { dispatch } = props

  // 1. 調用dva附加在組件props上的dispatch方法,發起一個action
  // 2. action是一個普通對象(plain object),通常包含type字段和payload字段(固然也能夠視狀況不傳payload)
  dispatch({

    // 3. type的值實際上相似一個尋址過程,編寫規則即namespace/reducerName|effectName

    // 4. dva根據你的namespace去找到對應的model,根據你的reducerName|effectName找到對應的reducer或者effect

    // 5. 回到咱們這個例子即:找到namespace爲user的model,並觸發一個名爲fetchCurrentUser的effect,payload爲空。

    // 注意:實際上第5點描述的就是這個對象的鍵值對,這就是action,一個描述動做的普通對象。
    type: 'user/fetchCurrentUser'
  })
}

export default connect(({ user }) => ({ user }))(SetUserInfoComponent)

如下部分是詳細說明:connect是一個高階函數,它接收一個mapStateToProps函數(固然你也能夠隨便叫它什麼名字,無非這個名字比較能闡明它的做用), 返回一個接收組件的函數。該組件加強函數是一個普通函數,接收組件,返回加強後的組件。使得加強後的組件能夠在內部經過props拿到dva中的statedva提供的dispatch函數html

// connect第一個形參函數,描述了須要從全局state映射到組件props上的指定部分狀態,該函數返回了一個對象內含狀態鍵值對
const mapStateToProps = ({ user }) => ({ user })

connect(mapStateToProps)(Component) => <EnhancedComponent {...props, user: GlobalState[user], dispatch: fn(){/* dispatch function code*/}}/>

//咱們能夠簡單想一下connect的實現形式可能相似以下代碼幫助理解
const connect = mapStateToPropsFunc => MetaComponent => {

  const state = mapStateToPropsFunc(dva.GlobalState)

  return <MetaComponent dispatch={dva.dispatch} {...state}/>
}
實際上翻閱 Dva源碼能夠知道connect方法就是由react-redux提供的(源碼看 這裏),Dva作的工做就是引入導出connect便於咱們統一在Dva中調用,即所謂的技術收斂。

3. 總體開發流程?

  1. 編寫你的業務組件
  2. 你意識到有些數據可能會跨組件使用
  3. 你爲其定義了一個Model,聲明瞭一個獨一無二的namespace
  4. 你開始思考會涉及到哪些同步異步的狀態處理
  5. 初始化state,編寫effects、reducers(看上面例子的model部分!)
  6. 回到你的業務組件並將其鏈接到dva上(看上面例子的connect部分!)
  7. 在合適的地方dispatch一個action執行相應的reducer/effect(看上面例子的dispatch部分!)

4. 想要了解Dva源碼?

請先閱讀官網的這篇文章。java

5. 更好的理解Dva?

  • 你須要熟悉一下redux的架構
  • 你須要理解react-redux的做用
  • 思考一下redux負責同步狀態的管理,那麼該如何處理異步狀態?
  • 看一下redux-thunk的源碼,並瞭解redux是怎麼用中間件思想讓狀態管理支持異步
  • redux-saga解決了什麼,它是如何處理異步狀態的
  • 整合構成了dva這一套狀態管理的最佳實踐,回過頭來看看文檔是否是很親切了。
相關文章
相關標籤/搜索