Dva 入门课之Model闲聊

2019-02-162157

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 了解更多

分享
点赞2
打赏
上一篇:代理工具Fiddler -调试与替换接口状态
下一篇:Lodash 中文文档