假期充電 Day 4 —— Dva 入門課之Model閒聊

廣州蘆葦科技web前端發表於2019-02-08

dva@2.4.1

dva 簡介

這裡就不過多冗餘了,引用官方文件的介紹:(詳細見:DvaJS - 介紹

dva 首先是一個基於 redux 和 redux-saga 的資料流方案,然後為了簡化開發體驗,dva 還額外內建了 react-router 和 fetch,所以也可以理解為一個輕量級的應用框架。

本文目標

今天先了解一下 Dva 中的核心 Model,相信很多剛看 Dva 的同學對 Model 裡面的內容有點懵,今天我們主要就聊聊 Model。

問題:

  1. namespace是什麼?有什麼作用
  2. Model中的 state 是什麼?
  3. Model中的 reducers 物件裡定義的函式的兩個引數add (state, action)是什麼?

我們基於官方的一個簡單例子——Count: 簡單計數器,改一下程式碼,嘗試讓其更容易理解

namespace 與 state

嘗試將上面連結中的程式碼換掉,使用附錄1的程式碼,然後開啟 Redux DevTools,對比一下修改前和修改後的區別,如下兩圖所示:

enter description here

enter description here

實際上,每定義一個 model,實際上就是在“資料樹”(最外面的物件)上掛一小塊,再嘗試將程式碼換成附錄2看看,如下圖

enter description here

enter description here

每定義一個 model,相當於在“資料樹”上定一個物件或者屬性

那麼 namespace 是什麼?——講到這裡就應該比較好理解了,namespace 只是“資料樹”這個物件的屬性名,如上圖的countschoolcompany。這就是namespace其中一個重要的作用。

namespace另外一個的重要作用是告訴 dispatch 函式,到底要執行哪個 model 中的哪個函式。

還是回到 附錄1 的程式碼:

props.dispatch({
          type: 'count/add',
          payload: 1,
})
複製程式碼

這裡,實際上 type: 'count/add' 就是告訴dispatch 函式,需要執行count這個 model 中的add函式(ps:add 可以寫在reducers中,也可以寫在effects中,這個以後再講)

以上,解答了開頭的前兩個問題,到這裡應該對 namespace 和 Model 中的 state 不陌生了吧

reducers

來,我們再看看第三個問題,到底 reducers 物件裡定義的函式的兩個引數add (state, action)是什麼?

請看附錄1的程式碼:

reducers: {
    add (state, action) {
      let num = state.num + action.payload;

      return {
        ...state,
        num,
      };
    },
  },
複製程式碼

第一個引數(state),指的是當前這個 model的 state 的值(附錄1的是namespace: 'count'這個 model)。如果什麼事情都沒發生,那麼此時的值應該是初始值,即:

{
    flag: '我是一個擺設',
    num: 0,
},
複製程式碼

第二個引數(action),指的是dispatch 函式的引數(整個物件):

props.dispatch({
          type: 'count/add',
          payload: 1,
})
複製程式碼

這時可以嘗試把程式碼換成附錄3,點一下加號,看看列印出來的是什麼

到這裡應該已經清晰這兩個引數到底是什麼了

但是還有一個問題,就是為什麼 add 函式的 return 要寫成:

return {
        ...state,
        num,
};
複製程式碼

細心的你應該不難發現,這裡就留一個探索題,試試把 ...state,,去掉,然後執行一下附錄1的程式碼,檢視一下 Redux DevTools,你肯定可以發現有什麼不妥。

一個小提示:

  1. ...stateES6物件的擴充套件運算子

附錄1

import React from 'react';
import dva, { connect } from 'dva';
import './style.css';

// 1. Initialize
const app = dva();

// 2. Model
app.model({
  namespace: 'count',
  state: {
    flag: '我是一個擺設',
    num: 0,
  },
  reducers: {
    add (state, action) {
      let num = state.num + action.payload;

      return {
        ...state,
        num,
      };
    },
  },
});

// 3. View
const App = connect(({ count }) => ({
  count
}))(function(props) {
  return (
    <div>
      <h2>{ props.count.num }</h2>
      <button key="add" onClick={() => { 
        props.dispatch({
          type: 'count/add',
          payload: 1,
        })
      }}>+</button>
    </div>
  );
});

// 4. Router
app.router(() => <App />);

// 5. Start
app.start('#root');

複製程式碼

附錄2

import React from 'react';
import dva, { connect } from 'dva';
import './style.css';

// 1. Initialize
const app = dva();

// 2. Model
app.model({
  namespace: 'count',
  state: {
    flag: '我是一個擺設',
    num: 0,
  },
  reducers: {
    add (state, action) {
      let num = state.num + action.payload;

      return {
        ...state,
        num,
      };
    },
  },
});

app.model({
  namespace: 'school',
  state: {
    flag: '我是一個擺設,我在 school 這個 model 中',
  },
  reducers: {
  },
});

app.model({
  namespace: 'company',
  state: {
    flag: '我是一個擺設,我在 company 這個 model 中',
  },
  reducers: {
  },
});



// 3. View
const App = connect(({ count }) => ({
  count
}))(function(props) {
  return (
    <div>
      <h2>{ props.count.num }</h2>
      <button key="add" onClick={() => { 
        props.dispatch({
          type: 'count/add',
          payload: 1,
        })
      }}>+</button>
    </div>
  );
});

// 4. Router
app.router(() => <App />);

// 5. Start
app.start('#root');

複製程式碼

附錄3

import React from 'react';
import dva, { connect } from 'dva';
import './style.css';

// 1. Initialize
const app = dva();

// 2. Model
app.model({
  namespace: 'count',
  state: {
    flag: '我是一個擺設',
    num: 0,
  },
  reducers: {
    add (state, action) {
      let num = state.num + action.payload;

      console.log(action);

      return {
        ...state,
        num,
      };
    },
  },
});

// 3. View
const App = connect(({ count }) => ({
  count
}))(function(props) {
  return (
    <div>
      <h2>{ props.count.num }</h2>
      <button key="add" onClick={() => { 
        props.dispatch({
          type: 'count/add',
          payload: 1,
          extra: {
            name: 'wuqinfa',
            age: 18
          }
        })
      }}>+</button>
    </div>
  );
});

// 4. Router
app.router(() => <App />);

// 5. Start
app.start('#root');

複製程式碼

作者簡介:吳勤發,蘆葦科技web前端開發工程師。擅長網站建設、公眾號開發、微信小程式開發、小遊戲、公眾號開發,專注於前端框架、服務端渲染、SEO技術、互動設計、影象繪製、資料分析等研究,有興趣的小夥伴來撩撩我們~ web@talkmoney.cn

訪問 www.talkmoney.cn 瞭解更多

相關文章