返回
DvaJS入门指南:详解umi2 + dva模式下的用户管理CURD应用构建
前端
2023-11-29 17:56:31
前言
最近一个月来,我一直在使用 dva 对公司存量项目进行重构,因此没有多少时间写文章。随着9月开学季的到来,我最近一直在使用的几个开源项目都迎来了重大更新。首先,umi 终于迎来了 2.0 版本,有关详细信息,请查看发布 umi 2.0,可插拔的企业级 react 应用框架。随之而来的是使用 umi 开发的新项目都必须使用 dva 版本 2.0 及以上。
项目搭建
首先,我们先创建一个新的umi项目,在命令行中输入以下命令:
npx create-umi my-app
然后,进入项目目录,安装 dva:
cd my-app
npm install dva dva-model
数据模型
接下来,我们需要定义我们的数据模型。在 src/models/user.js
中,我们创建了一个名为 user
的模型:
import { defineModel } from 'dva';
export default defineModel({
namespace: 'user',
state: {
list: [],
total: 0,
page: 1,
pageSize: 10,
},
effects: {
*fetchUsers({ payload }, { call, put }) {
const response = yield call(fetch, '/api/users', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const data = yield response.json();
yield put({
type: 'saveUsers',
payload: data,
});
},
*createUser({ payload }, { call, put }) {
const response = yield call(fetch, '/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const data = yield response.json();
yield put({
type: 'addUser',
payload: data,
});
},
*updateUser({ payload }, { call, put }) {
const response = yield call(fetch, `/api/users/${payload.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const data = yield response.json();
yield put({
type: 'modifyUser',
payload: data,
});
},
*deleteUser({ payload }, { call, put }) {
const response = yield call(fetch, `/api/users/${payload.id}`, {
method: 'DELETE',
});
yield put({
type: 'removeUser',
payload: payload,
});
},
},
reducers: {
saveUsers(state, { payload }) {
return {
...state,
list: payload.data,
total: payload.total,
};
},
addUser(state, { payload }) {
return {
...state,
list: [...state.list, payload],
};
},
modifyUser(state, { payload }) {
const index = state.list.findIndex(item => item.id === payload.id);
return {
...state,
list: [
...state.list.slice(0, index),
payload,
...state.list.slice(index + 1),
],
};
},
removeUser(state, { payload }) {
return {
...state,
list: state.list.filter(item => item.id !== payload.id),
};
},
},
});
路由配置
接下来,我们需要配置路由。在 src/routes.js
中,我们添加以下代码:
export default [
{
path: '/users',
component: '@/pages/users/index',
},
];
组件编写
现在,我们可以编写组件了。在 src/pages/users/index.js
中,我们创建了一个名为 Users
的组件:
import { connect } from 'dva';
import { Table, Button, Modal, Form, Input } from 'antd';
const Users = ({ dispatch, loading, list, total, page, pageSize }) => {
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '操作',
key: 'action',
render: (text, record) => (
<span>
<Button type="primary" onClick={() => handleEdit(record)}>编辑</Button>
<Button type="danger" onClick={() => handleDelete(record)}>删除</Button>
</span>
),
},
];
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const handleEdit = (record) => {
setVisible(true);
form.setFieldsValue(record);
};
const handleDelete = (record) => {
dispatch({
type: 'user/deleteUser',
payload: record,
});
};
const handleOk = () => {
form
.validateFields()
.then((values) => {
if (values.id) {
dispatch({
type: 'user/updateUser',
payload: values,
});
} else {
dispatch({
type: 'user/createUser',
payload: values,
});
}
setVisible(false);
form.resetFields();
})
.catch((err) => {
console.log(err);
});
};
const handleCancel = () => {
setVisible(false);
form.resetFields();
};
const pagination = {
total,
current: page,
pageSize,
onChange: (page, pageSize) => {
dispatch({
type: 'user/fetchUsers',
payload: {
page,
pageSize,
},
});
},
};
return (
<>
<Button type="primary" onClick={() => setVisible(true)}>新建用户</Button>
<Table columns={columns} dataSource={list} loading={loading} pagination={pagination} />
<Modal
title="编辑用户"
visible={visible}
onOk={handleOk}
onCancel={handleCancel}
>
<Form form={form}>
<Form.Item name="id" hidden={true}>
<Input />
</Form.Item>
<Form.Item label="姓名" name="name" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item label="年龄" name="age" rules={[{ required: true }]}>
<Input />
</Form.Item>
</Form>
</Modal>
</>
);
};
export default connect(({ user, loading }) => ({
list: user.list,
total: user.total,
page: user.page,
pageSize: user.pageSize,
loading: loading.effects['user/fetchUsers'],
}))(Users);
服务端接口开发
最后,我们需要开发服务端接口。在 src/server/index.js
中,我们添加以下代码:
const express = require('express');
const app = express();
const port = 3000;
app.get('/api/users', async (req, res) => {
const users = await User.find();
res.json({
data: users,
total: users.length,
});
});
app