概览
React 是什么?
React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。使用 React 可以将一些简短、独立的代码片段组合成复杂的 UI 界面,这些代码片段被称作“组件”。
antd 是什么?
antd 是基于 Ant Design 设计体系的 React UI 组件库,主要用于研发企业级中后台产品。
umi 是什么?
umi,中文可发音为乌米,是可扩展的企业级前端应用框架。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。
dva 是什么?
dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。
目标
使用React+AntD+Dva+Umi构建一个非常简单CRUD应用程序,以便您更好地了解它的工作方式。
完整的 demo 代码请访问 https://github.com/zcqiand/crud
演示
列表页面
添加页面
编辑页面
构建
脚手架创建React应用
先找个地方建个空目录,通过官方工具创建项目
mkdir demo1 && cd demo1
yarn create @umijs/umi-app
安装依赖
yarn
启动项目
yarn start
一旦运行此命令,http://localhost:8000新的React应用程序将弹出一个新窗口。
构建路由
修改.umirc.js代码
export default {
routes: [
{
path: '/',
component: '../layouts/index',
routes: [
{ path: '/', component: '../pages/goods/index' },
{ path: '/goods/add', component: '../pages/goods/add' },
{ path: '/goods/:id/edit', component: '../pages/goods/edit' }
]
}
],
dva: {},
antd: {},
proxy: {
"/api": {
target: "http://localhost:59367/",
changeOrigin: true,
pathRewrite: {
'^/api': '',
},
},
},
}
构建列表页面
import React, { Component } from "react";
import { Table, Popconfirm, Button } from 'antd';
import { connect } from 'umi';
@connect(state => ({
items: state.goods.items,
}))
export default class GoodsIndex extends Component {
constructor(props) {
super(props)
}
componentDidMount() {
this.queryGoods()
}
queryGoods() {
console.log('queryGoods');
this.props.dispatch({
type: 'goods/query',
})
}
addGoods = () => {
console.log('addGoods');
window.location.pathname = "/goods/add";
}
editGoods = (id) => {
console.log('editGoods');
window.location.pathname = `/goods/${id}/edit`;
}
deleteGoods = (id) => {
console.log('deleteGoods:' + id);
this.props.dispatch({
type: 'goods/delete',
payload: id
})
}
render() {
const items = this.props.items || []
console.log(items)
const columns = [
{
title: '名称',
dataIndex: 'Name',
key: 'Name',
},
{
title: '描述',
dataIndex: 'Describe',
key: 'Describe',
},
{
title: '操作',
key: 'action',
render: (record) => (
this.deleteGoods(record.Id)}>
),
},
];
return (
)
}
}
构建添加页面
import React, { Component } from "react";
import { Form, Input, Button } from 'antd';
import { connect } from 'umi';
const { TextArea } = Input;
@connect()
export default class GoodsAdd extends Component {
render() {
const onFinish = values => {
console.log('onFinish:', values);
this.props.dispatch({
type: 'goods/create',
payload: values
})
};
const onFinishFailed = errorInfo => {
console.log('onFinishFailed:', errorInfo);
};
return (
)
}
}
构建编辑页面
import React, { Component } from "react";
import { Form, Input, Button } from 'antd';
import { connect } from 'umi';
const { TextArea } = Input;
@connect(state => ({
item: state.goods.item,
}))
export default class GoodsEdit extends Component {
formRef = React.createRef();
constructor(props) {
super(props)
}
componentDidMount() {
this.getGoods(this.props.match.params.id)
}
componentDidUpdate() {
const item = this.props.item
this.formRef.current.setFieldsValue({
Name: item.Name,
Describe: item.Describe,
});
}
getGoods(id) {
this.props.dispatch({
type: 'goods/get',
payload: id
})
}
render() {
const onFinish = values => {
console.log('onFinish:', values);
let param = values
param.Id = this.props.match.params.id
this.props.dispatch({
type: 'goods/update',
payload: param
})
};
const onFinishFailed = errorInfo => {
console.log('onFinishFailed:', errorInfo);
};
return (
)
}
}
构建Model
import { queryGoods, getGoods, createGoods, updateGoods, deleteGoods } from '../services/goods';
import { history } from 'umi';
export default {
namespace: 'goods',
state: {
items: [], //列表记录
item: {}, //当前记录
},
effects: {
*query(_, { call, put }) {
const ret = yield call(queryGoods);
console.log(ret)
if (ret && ret.Code === 0) {
yield put({
type: 'querySuccess',
payload: {
items: ret.Result
},
});
}
},
*get({ payload }, { call, put }) {
console.log(payload)
const ret = yield call(getGoods, payload);
console.log(ret)
if (ret && ret.Code === 0) {
yield put({
type: 'getSuccess',
payload: {
item: ret.Result
},
});
}
},
*create({ payload }, { call, put }) {
console.log(payload)
const ret = yield call(createGoods, payload);
if (ret && ret.Code === 0) {
history.push('/');
}
},
*update({ payload }, { call, put }) {
console.log(payload)
const ret = yield call(updateGoods, payload.Id, payload);
if (ret && ret.Code === 0) {
history.push('/');
}
},
*delete({ payload }, { call, put }) {
console.log(payload)
const ret = yield call(deleteGoods, payload);
if (ret && ret.Code === 0) {
yield put({
type: 'deleteSuccess',
payload: {
Id: payload
},
});
}
},
},
reducers: {
querySuccess(state, action) {
return { ...state, ...action.payload };
},
getSuccess(state, action) {
return { ...state, ...action.payload };
},
deleteSuccess(state, { payload: o }) {
const items = state.items.filter(item => item.Id !== o.Id);
return { ...state, items };
},
},
};
构建Service
import request from '../../../utils/request';
import qs from 'qs';
export function queryGoods() {
return request(`/api/examplemodule/goods`);
}
export function getGoods(id) {
return request(`/api/examplemodule/goods/${id}`);
}
export function createGoods(param) {
return request(`/api/examplemodule/goods/create`, {
method: 'post',
body: qs.stringify(param),
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
});
}
export function updateGoods(id, param) {
return request(`/api/examplemodule/goods/${id}/update`, {
method: 'post',
body: qs.stringify(param),
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
});
}
export function deleteGoods(id) {
return request(`/api/examplemodule/goods/${id}/delete`, {
method: 'post',
});
}
参考
- https://react.docschina.org/docs/getting-started.html
- https://reacttraining.com/react-router/web/guides/quick-start
- https://ant.design/index-cn
- https://umijs.org/zh-CN
- https://dvajs.com/guide/