Ant Design中的dva流程梳理

文章目录

功能

dva流程简单来说就是model层和view层的分离,数据的存储不放在组件的state中,单独拎出来放在model中。项目开发过程中个人感觉全局性数据(比如用户名,用户权限)可以采用这种方法实现。

本例中page层页面List.js负责显示,数据和更新数据的方法放在model层中的DataList.js中。实现效果如下:

在这里插入图片描述

代码

  • page层:src/routes/List.js
import React from 'react';
//dva是1种分层想,将page(routes/List.js)和model(models/ListData.js)进行分层
//其中page只负责页面显示,数据在model中进行处理
import {connect} from 'dva';


const namespace = 'list';

//说明:第1个回调函数将page层和model层进行连接,返回model中的数据
//并且将返回的数据绑定到this.props中,下面通过this.props.dataList拿数据
//注意不是this.state.dataList
//第2个回调函数,将定义的函数绑定到this.props中,可以调用model层中定义的函数
//通过this.props.add()操作,不是this.state.add()

//*******************以下是第1种写法,直接把2个回调函数写入*******************
//dva的作用是connect model和page
//2个回调函数作为参数
//参数1:将page和model进行连接,返回modle中的数据,并且将返回的数据绑定到this.props
//参数2:将返回的函数绑定到this.props
@connect((state) => {//state是整个项目全局的state,通过命名空间获取指定的model的state
  return {//返回1个对象,将返回的值绑定到this.props中
    dataList: state[namespace].data,
    maxNum: state[namespace].maxNum
  }
}, (dispatch) => {//dispatch的作用:可以调用model层定义的函数
  return {//将返回的函数,绑定到this.props中
    add() {
      dispatch({
        type: 'list/addNewData'  //model的namespace + model中定义的函数名
      });
    },
    init: () => {//箭头函数写法
      dispatch({
        type: 'list/initData'
      });
    }
    //下面可以定义多个函数
  }
})
//*******************以上是第1种写法*******************

//*******************以下是第2种写法*******************
// const mapStateToProps = (state) => {
//   return {//返回1个对象
//     dataList: state[namespace].data,
//     maxNum: state[namespace].maxNum
//   }
// };
//
// const mapDispatchToProps = (dispatch) => {
//   return {//将返回的函数,绑定到this.props中
//     add() {
//       dispatch({
//         type: 'list/addNewData'  //model的namespace + model中定义的函数名
//       });
//     },
//     init() {
//       dispatch({
//         type: 'list/initData'
//       });
//     }
//     //下面可以定义多个函数
//   }
// };
//
// @connect(mapStateToProps, mapDispatchToProps)
//*******************以上是第2种写法*******************


class List extends React.Component {
  //构造函数其实没用,因为props都是从model中获取
  // constructor(props) {
  //   super(props);
  //
  //   //初始化数据分离到model层
  //   this.state = {
  //     dataList: [1, 2, 3],
  //     maxNum: 3
  //   }
  // }

  //生命周期函数
  componentDidMount() {
    //组件加载完成后初始化操作
    this.props.init();
  }

  render() {
    return (
      <div>
        <ul>
          {
            this.props.dataList.map((value, index) => {
              return <li key={index}>{value}</li>
            })
          }
        </ul>
        <button onClick={() => {
          this.props.add();
        }}>点击
        </button>
      </div>
    )
  }
}

export default List
  • model层:src/models/listData.js
//effects中的request对象
import request from "../utils/request";

export default {
  namespace: 'list', //src/models中所有的model通过namespace进行区分
  state: {//state传入下面的addNewData函数
    data: [],
    maxNum: 1
  },

  //新增effects配置,用于异步加载数据
  effects: {
    //initData在route层页面加载后调用,componentDidMount中调用
    * initData(params, {call, put}) {//定义异步方法(*表示异步方法 ),获取到call,put方法
      const url = '/ds/list';  //定义请求的url,具体初始化数据在mock中,注意开始有反斜杠/,和mock对应
      //执行请求,result表示拿到的数据,call中的参数request就是导入的utils/request.js
      let result = yield call(request, url);
      yield put({ //调用reducers中的方法,传递到addNewData里面的result参数
        type: 'addNewData',  //指定方法名,调用reducers中的addNewData
        data: result.data, //传递ajax回来的数据,后面的result是ajax拿到的数据,前面的data是定义的state属性名
        maxNum: result.maxNum
      });
    }
  },

  //model层新增reducer方法,用于更新state中的数据
  reducers: {
    addNewData(state, result) {//参数state指的是更新之前的state数据,result代表ajax请求到的数据
      if (result.data) {//如果state中存在data数据,直接返回,在做初始化的操作
        return result.data;  //返回更新后的数据
      }

      let maxNum = state.maxNum + 1;
      let newArr = [...state.data, maxNum];  //形成新的数组

      //更新状态数据
      return {//通过return返回更新后的数据,不是setState
        data: newArr,
        maxNum: maxNum
      }
    }
  }
}

  • 路由src/router.js
import React from 'react';
import {Router, Route, Switch} from 'dva/router';
import List from './routes/List';


function RouterConfig({history}) {
  return (
    <Router history={history}>
      <Switch>
        <Route path="/" exact component={List}/>
      </Switch>
    </Router>
  );
}

export default RouterConfig;
  • request对象:src/utils/request.js
import fetch from 'dva/fetch';

function parseJSON(response) {
  return response.json();
}

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  }

  const error = new Error(response.statusText);
  error.response = response;
  throw error;
}

/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
export default function request(url, options) {
  return fetch(url, options)
    .then(checkStatus)
    .then(parseJSON)
    .then(data => ({ data }))
    .catch(err => ({ err }));
}
  • mock数据:mock/MockListData.js
export default {
  "GET /ds/list": function (req, res) {//模拟请求返回数据
    res.json({
      data: [1, 2, 3, 4],
      maxNum: 4
    });
  }
}
  • 开启mock: .roadhogrc.mock.js
export default {
  ...require('./mock/MockListData')
};

整体代码:https://github.com/nuptcheng/dva-list-demo.git

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值