理解 dva

簡介

官網上介紹:dva 是基於redux,redux-saga和react-router的輕量級前端框架。也就是 dva 主要是基於 redux 和 redux-saga 的數據流解決方案,內置了 react-router 和 fetch。javascript

從何處開始接觸

dva 是 antd design pro 基於 React 的中後臺管理控制檯的腳手架選擇的數據流管理框架,作 antd-pro 搭建的項目的時候開始接觸到這個框架,在腳手架造成的目錄中:dva 分別在 '/src/models' 中管理全局數據,在 '/pages/肯定的某一頁面/models' 中管理某一頁面的數據。html

結合代碼理解

下面代碼是在 antd-pro 腳手架搭建起來的項目中的實踐,原理部分的掌握還欠缺,先記下來經常使用的用法,和基礎知識。前端

  1. 這多是在 page 中的一段簡單代碼,組件要改變當前狀態須要調用 dispatch 函數驅動 dva model state 的改變,改變後的 state 再經過 connect 注入到組件中:
// connect 也是鏈接的數據是對 store 中的數據的淺複製,當是引用類型的數據的時候,若是直接修改 props 中映射數據, store 裏面的數據也會被修改
@connect(state => ({
  detailsTable: state['event/addNewCard'],// 這裏傳入的 state 參數是一個「徹底體」,包含了全部 namespace 下的 state,以 namespace 爲 key 值進行區分
  loading: state.loading,
  layout: state.layout,
}))
export default class PuzzleCardsPage extends Component {
  addNewCard(){
    dispatch({
        type:'event/addNewCard',
        payload:{},//傳遞數據的載體
        //還能夠傳進去一個回調函數,處理當數據沒有正確請求的時候的處理邏輯
        callback: res => {
            message.error(res)
        }
    })
  }
  render() {
    return (
        <div> <Button onClick={this.addNewCard}> 添加卡片 </Button> </div>
    );
  }
}
複製代碼
  1. model 是 dva 中最重要的一個概念,一個簡單的 model 示例以下:
export default {
    namespace: '',//不一樣的頁面或操做對應不一樣的命名空間
    state:{},
    effects:{//至關於 redux 的 middleware,爲了保證 reducer 的純粹性,有一些須要對數據在進行處理的操做放在 effects 裏面,好比在 effects 裏面能夠調用 services 方法進行異步請求。
        *addByONe({payload, error}, { call, put, select }) { // 傳入這個 Generator 函數的有兩個參數,一個是匹配這個 effects 的 action 對象,所以能夠取到 payload 和 error 字段。 另外一個是 effect 原語集,call 主要處理異步邏輯(好比發起請求)它第一個參數是一個函數,要求函數返回 Promise,以後的參數是該函數調用時的入參。
          const num = yield select(state => state.num)    // effects 裏面主要經過yield select 獲取 state
          let param1;
          param1 = num + param;
          yield put({//effects 裏面經過 put 方法觸發 action,和 pages 中的dispatch 方法如出一轍,能夠繼續請求其餘 namespace 中的 effects 或者 reducer ,不一樣的是,請求自身的 effects 或者 reducer 時不須要指定 namespace 名稱
             type: 'save',   
             num:param1
      });
    }
    },
    //用來保存更新 state 值 上面的 put 方法調用這裏的方法,當不須要發起請求,只修改state中數據的方法放在這裏,且這裏的方法也可以被外部調用
  reducers: {
    save(state, action) { //state 是當前命名空間的 state,這裏的 action 包含了上面傳遞的參數和 type
      return { ...state, ...action.num }; 
    },
  },
}
複製代碼

model 中幾個基本屬性,其中 namespace 和 state 是一個 model 中最基本的兩個成員。java

  • namespace:model 的命名空間,只能用字符串,是一個 model 的惟一標識。一個大型應用可能包含多個 model,經過 namespace 區分。
  • state:當前 model 狀態的初始值,表示當前狀態。是該 model 管理的數據
  • reducers:用於處理同步操做,更新修改 state,由 action 觸發。reducer 是一個純函數,它接受當前的 state 及一個 action 對象。action 對象裏面能夠包含數據體(payload)做爲入參,須要返回一個新的 state。
  • effects:用於處理異步操做(例如:與服務端交互)和複雜的數據處理邏輯,也是由 action 觸發。可是,它不能夠修改 state,要經過觸發 action 調用 reducer 實現對 state 的間接操做。
  • action:是 reducers 及 effects 的觸發器,通常是一個對象,形如{ type: 'add', payload: todo },經過 type 屬性能夠匹配到具體某個 reducer 或者 effect,payload 屬性則是數據體,用於傳送給 reducer 或 effect。
  1. 若是想知道數據請求函數是否執行完畢,須要加載 dva-loading 插件,可是使用腳手架搭建項目,直接在頁面中使用就能夠了,經過 connect 方法將加載的狀態傳遞到組件中,下面是幾種具體的方法:

(1)loading.effects['chart/fetch'] 監聽這個方法是否執行完畢,若執行完畢。loading 的值就變爲 false。react

@connect(({ chart, loading }) => ({
  chart,
  loading: loading.effects['chart/fetch'],
}))
複製代碼

(2)loading.models.monitor 監聽這個模塊是否執行完畢,注意這裏的 [monitor] 是命名空間。監聽的是當前頁面用到的命名空間裏面的方法。若執行完畢,loading 的狀態變爲 false。git

@connect(({ monitor, loading }) => ({
  monitor,
  loading: loading.models.monitor,
}))
複製代碼

(3)還有一種用法是 loading.global,經過全局的狀態控制 loading 的狀態。loading.global監聽這個頁面的加載狀態。當頁面處於異步加載狀態時該值爲 true,當頁面加載完成時,自動監聽該值爲 false。github

這裏是綁定到 dva 的自動控制 loading 數據的插件。再也不須要重複寫 showLoading 和 hideLoading。redux

當不使用 antd-pro 腳手架搭建項目使用 dva 時

文檔中講的很清楚,並且在掌握上面的基礎知識後,也不難上手使用這個框架。前端框架

// 建立應用
const app = dva();

// 註冊 Model
app.model({
  namespace: 'count',
  state: 0,
  reducers: {
    add(state) { return state + 1 },
  },
  effects: {
    *addAfter1Second(action, { call, put }) {
      yield call(delay, 1000);
      yield put({ type: 'add' });
    },
  },
});

// 註冊視圖
app.router(() => <ConnectedApp />);

// 啓動應用,將組件掛載到 id 爲 root 的元素上
app.start('#root');
複製代碼

參考

dva-loading 實踐用法
github
dva官網指南antd

相關文章
相關標籤/搜索