# Dva 笔记

dva (opens new window)是国内蚂蚁大佬在 react 基础上做的一层封装的轻量框架,深受大家喜欢,而且我司 react 项目也是基于 dva 上写的,所以本文记录学习框架的笔记

# 初始化

起步项目,然后快速构建一个项目。

  1. routes下新建一个产品组件

    import React from "react";
    
    const Demo = () => {
      return <h2>111</h2>;
    };
    
    export default Demo;
    
  2. router,js添加路由信息

    import Demo from "./routes/demo";
    
    <switch>
      <Route path="/demo" exact component={Demo}></Route>
    </switch>;
    

# 新建页面

新建一个页面需要做的事情

首先在routes下新建容器组件,该组件的作用就是连接UI组件将数据传给UI组件

一般参数就是解构propsdispatch和 state 的数据

import React from "react";
import { connect } from "dva";
import ProductList from "../components/ProductList";

const Products = ({ dispatch, products }) => {
  function handleDelete(id) {
    dispatch({
      // action在model层中定义,type为namespace+type拼接 payload表示传递参数
      type: "products/delete",
      payload: id
    });
  }
  return (
    <div>
      //传递数据给UI组件
      <ProductList onDelete={handleDelete} products={products}></ProductList>
    </div>
  );
};
// 每个参数都是返回一个对象,第一个是state里的数据映射到props
export default connect(({ products }) => ({
  products
}))(Products);

接下来就是分别书写modelUI组件

// model层组要是操作store中的数据和定义reducers和异步操作的effects
export default{
  // 每个state都有key值,调用dispatch时需要拼接到type前
  namespace:'products',
  state:[],
  reducers:{
    'delete'(state,{payload:id}){
      return state.filter(item=>item.id !== id)
    }
  },
  effects:{
    ...
  }
}

UI组件 接受容器组件传递过来的事件和数据,然后绑定事件操作数据

import React from "react";
import ProTypes from "prop-types";
import { Popconfirm, Button, Table } from "antd";

const ProductList = ({ onDelete, products }) => {
  const columns = [
    {
      title: "Name",
      dataIndex: "name"
    },
    {
      title: "Actions",
      render: (text, record) => {
        return (
          <Popconfirm title="onDelete?" onConfirm={() => onDelete(record.id)}>
            <Button type="primary">Delete</Button>
          </Popconfirm>
        );
      }
    }
  ];
  return <Table dataSource={products} columns={columns}></Table>;
};
// 校验props
ProductList.prototype = {
  onDelete: ProTypes.func.isRequired,
  products: ProTypes.array.isRequired
};
export default ProductList;

最后就是定义路由

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

# 同步 action 和异步 action

Reducer

model分开时

export default {
  namespace:'products',
  state:[],
  reducers:{
    'delete'(state,{payload:id}){
      return state.filter(item=>item.id !== id)
    }
    ....
  }
}

Effect

export default{
  namespace:‘todos’,
  effects:{
    // 定义函数添加上*通配符
      * getExpress({ payload }, { call, put }) {
      const response = yield call(Services.orderExpress, payload);
      yield put({
        type: 'queryExpress',
        payload: response,
      });
    }
  }
}

底层使用到了redux-saga实现,语法上使用到了ES6generator函数

主要记住这几个 API

  • call

    用于调用 API 请求 call(func,...args)

    const response = yield call(Services.queryStatistic, payload);
    
  • put

    触发action更新数据

     yield put({
      type: 'getStatistic',
      payload: response,
    });
    
  • takeEvery

    监听 action,监听到就调用方法

    function* mySaga() {
      yield takeEvery(actionType, method);
    }
    
Last update: 7/20/2021, 8:53:54 AM