dva 是什么(DvaJS 原理及源碼解析)


截止 2017.1,最流行的社區 React 應用架構方案如下。

缺點:要引入多個庫,項目結構復雜。

dva 是什么

dva 是 React 應用框架,將上面三個 React 工具庫包裝在一起,簡化了 API,讓開發 React 應用更加方便和快捷。

dva = React-Router + Redux + Redux-saga

dva 應用的最簡結構

import dva from 'dva';
const App = () => <div>Hello dva</div>;

// 創建應用
const app = dva();
// 注冊視圖
app.router(() => <App />);
// 啟動應用
app.start('#root');

數據流圖

核心概念

  • State:一個對象,保存整個應用狀態
  • View:React 組件構成的視圖層
  • Action:一個對象,描述事件
  • connect 方法:一個函數,綁定 State 到 View
  • dispatch 方法:一個函數,發送 Action 到 State

State 和 View

State 是儲存數據的地方,收到 Action 以后,會更新數據。

View 就是 React 組件構成的 UI 層,從 State 取數據后,渲染成 HTML 代碼。只要 State 有變化,View 就會自動更新。

Action

Action 是用來描述 UI 層事件的一個對象。

{
  type: 'click-submit-button',
  payload: this.form.data
}

connect 方法

connect 是一個函數,綁定 State 到 View。

import { connect } from 'dva';

function mapStateToProps(state) {
  return { todos: state.todos };
}
connect(mapStateToProps)(App);

connect 方法返回的也是一個 React 組件,通常稱為容器組件。因為它是原始 UI 組件的容器,即在外面包了一層 State。

connect 方法傳入的第一個參數是 mapStateToProps 函數,mapStateToProps 函數會返回一個對象,用於建立 State 到 Props 的映射關系。

dispatch 方法

dispatch 是一個函數方法,用來將 Action 發送給 State。

dispatch({
  type: 'click-submit-button',
  payload: this.form.data
})

dispatch 方法從哪里來?被 connect 的 Component 會自動在 props 中擁有 dispatch 方法。

connect 的數據從哪里來?

dva 應用的最簡結構(帶 model)

// 創建應用
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 />);

// 啟動應用
app.start('#root');

數據流圖 1

數據流圖 2

app.model

dva 提供 app.model 這個對象,所有的應用邏輯都定義在它上面。

const app = dva();

// 新增這一行
app.model({ /**/ });

app.router(() => <App />);
app.start('#root');

Model 對象的例子

{
  namespace: 'count',
  state: 0,
  reducers: {
    add(state) { return state + 1 },
  },
  effects: {
    *addAfter1Second(action, { call, put }) {
      yield call(delay, 1000);
      yield put({ type: 'add' });
    },
  },
}

Model 對象的屬性

  • namespace: 當前 Model 的名稱。整個應用的 State,由多個小的 Model 的 State 以 namespace 為 key 合成
  • state: 該 Model 當前的狀態。數據保存在這里,直接決定了視圖層的輸出
  • reducers: Action 處理器,處理同步動作,用來算出最新的 State
  • effects:Action 處理器,處理異步動作

Reducer

Reducer 是 Action 處理器,用來處理同步操作,可以看做是 state 的計算器。它的作用是根據 Action,從上一個 State 算出當前 State。

一些例子:

// count +1
function add(state) { return state + 1; }

// 往 [] 里添加一個新 todo
function addTodo(state, action) { return [...state, action.payload]; }

// 往 { todos: [], loading: true } 里添加一個新 todo,並標記 loading 為 false
function addTodo(state, action) {
  return {
    ...state,
    todos: state.todos.concat(action.payload),
    loading: false
  };
}

Effect

Action 處理器,處理異步動作,基於 Redux-saga 實現。Effect 指的是副作用。根據函數式編程,計算以外的操作都屬於 Effect,典型的就是 I/O 操作、數據庫讀寫。

function *addAfter1Second(action, { put, call }) {
  yield call(delay, 1000);
  yield put({ type: 'add' });
}

Generator 函數

Effect 是一個 Generator 函數,內部使用 yield 關鍵字,標識每一步的操作(不管是異步或同步)。

call 和 put

dva 提供多個 effect 函數內部的處理函數,比較常用的是 call 和 put

  • call:執行異步函數
  • put:發出一個 Action,類似於 dispatch

參考:dva 是什么


免責聲明!

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



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