一、介绍umi
Umi官网:https://umijs.org/
- Umi 是蚂蚁金服的底层前端框架(经蚂蚁内部 3000+ 项目验证)
- Umi 是以'路由'为基础的企业级React框架(同时支持配置式路由和约定式路由)
- Umi 是一个'可插拔'的企业级React框架(内部功能完全使用插件化完成)
- 总结就是 Umi 是一个蚂蚁金服底层的, 以'路由'为基础的, 内部功能完全使用插件化完成的 React 框架
在这里怎么创建以及启动就不赘述了,官网已经有教程了,按照要求来即可。
二、Umi的目录结构
├── config // 配置文件
│ └── config.ts
├── dist
├── mock // 模拟请求
│ └── app.ts|tsx
├── src
│ ├── .umi
│ ├── .umi-production
│ ├── layouts // 页面框架
│ │ ├── BasicLayout.tsx
│ │ ├── index.less
│ ├── models // 全局模块
│ │ ├── global.ts
│ │ └── index.ts
│ ├── pages // 页面
│ │ ├── index.less
│ │ └── index.tsx
│ ├── utils // 推荐目录
│ │ └── index.ts
│ ├── services // 推荐目录
│ │ └── api.ts
│ ├── app.(ts|tsx)
│ ├── global.ts
│ ├── global.(css|less|sass|scss)
│ ├── overrides.(css|less|sass|scss)
│ ├── favicon.(ico|gif|png|jpg|jpeg|svg|avif|webp)
│ └── loading.(tsx|jsx)
├── node_modules // 无需介绍
│ └── .cache
│ ├── bundler-webpack
│ ├── mfsu
│ └── mfsu-deps
├── .env // 环境配置
├── plugin.ts // 插件配置
├── .umirc.ts // 与 config/config 文件 2 选一
├── package.json // 无需介绍
├── tsconfig.json // 无需介绍
└── typings.d.ts // 无需介绍
在这里使用Umimax框架,基于react和antd pro框架
因此,在学习UmiMax框架的同时,还需要数据antd pro框架的封装思想。
Ant Design Pro : https://pro-components.antdigital.dev/
简介:重型组件区别于传统组件有个很大的不同,重型组件在抽象时是将其当成一个页面来进行处理,所以 ProTable 会支持网络请求和自动生成查询表单,而 ProLayout 会支持自动生成菜单,两者都基于同样的思想也就是提供页面级别的抽象。
一个列表页应该可以用 ProLayout + ProTable 完成,一个编辑页应该使用 ProLayout + ProForm 完成,详情页可以用 ProLayout + ProDescriptions 完成。 一个页面在开发过程中只需要关注几个重型组件,降低心智负担,专注于更核心的业务逻辑。
创建页面
按照 Umi 的命名规范,在 pages 中创建目录,例如我现在需要一个产品管理页面
- 创建 Production 目录;
- 在 Productiion 目录下搭建页面
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { Button } from 'antd';
import React, { useRef, useState } from 'react';
import CreateOrEdit from './Modal';
const data = [
{
id: 1,
name: '1111',
info: '这是一条产品信息',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料',
},
{
id: 2,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
{
id: 3,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
{
id: 4,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
{
id: 5,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
{
id: 6,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
{
id: 7,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
{
id: 8,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
{
id: 9,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
{
id: 10,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
{
id: 11,
name: '2222',
info: '这是一条产品信息2',
img: 'http://abc.ariessui.asia/EEE6269F-963A-4137-994E-E9EE455A595C_1_105_c.jpeg',
material: '材料2',
},
];
const ProductionPage: React.FC = () => {
type TableListItem = {
id: number;
name: string;
info: string;
img: string;
material: string;
};
const actionRef = useRef<ActionType>();
const [isModalVisible, setIsModalVisible] = useState(false);
const [forms, setForms] = useState({});
//控制模态框显示隐藏
const isShowModal = (show: boolean, forms?: any) => {
console.log(forms);
setForms(forms);
setIsModalVisible(show);
};
const columns: ProColumns<TableListItem>[] = [
{
title: 'ID',
dataIndex: 'id',
ellipsis: true,
align: 'center',
search: false,
width: '50',
},
{
title: '图片预览',
align: 'center',
search: false,
render: (_, row) => {
return <img src={row.img} width={100}></img>;
},
},
{
title: '产品名称',
dataIndex: 'name',
align: 'center',
search: true,
},
{
title: '图片',
dataIndex: 'img',
align: 'center',
search: false,
},
{
title: '产品信息',
dataIndex: 'info',
align: 'center',
search: false,
},
{
title: '产品材料',
dataIndex: 'material',
align: 'center',
search: false,
},
{
title: '操作',
valueType: 'option',
render: (text, record, _, action) => [
<a
key="editable"
onClick={() => {
isShowModal(true, record);
}}
>
编辑
</a>,
],
},
];
// function queryCustomer(
// params: import('@ant-design/pro-provider').ParamsType & {
// pageSize?: number | undefined;
// current?: number | undefined;
// keyword?: string | undefined;
// },
// ): any {
// throw new Error('Function not implemented.');
// }
const handleClickCreate = () => {
isShowModal(true, {});
};
return (
<PageContainer ghost>
<ProTable<TableListItem>
rowKey="id"
actionRef={actionRef}
columns={columns}
headerTitle="全部数据"
dataSource={data}
search={{
labelWidth: 'auto',
}}
pagination={{
showQuickJumper: true,
}}
toolBarRender={() => [
<Button
type="primary"
key="create"
onClick={() => handleClickCreate()}
>
添加
</Button>,
]}
params={{ page: 'MY' }}
// request={async (params = {}) => {
// const response = (await queryCustomer(params)) as any;
// const {
// data: { data, total },
// success,
// } = response;
// return {
// data,
// total,
// success,
// };
// }}
/>
{!isModalVisible ? (
''
) : (
<CreateOrEdit
isModalVisible={isModalVisible}
isShowModal={isShowModal}
actionRef={actionRef}
forms={forms}
/>
)}
</PageContainer>
);
};
export default ProductionPage;
- 创建 Modal 框组件:在 Production 页面下面创建 Modal 目录
// import { addUser, showUser, updateUser } from '@/services/user';
import ProForm, { ProFormText } from '@ant-design/pro-form';
import { Modal } from 'antd';
import { useState } from 'react';
const CreateOrEdit = (props: any) => {
const { isModalVisible } = props;
const { isShowModal } = props;
const { actionRef } = props;
const { forms } = props;
const [initialValues, setInitialValues] = useState(forms);
const title = forms.id === undefined ? '添加产品信息' : '编辑产品信息';
//定义form实例用来操作表单
const [formObj] = ProForm.useForm();
const createUser = async (values: any) => {
console.log(values);
// message.success('提交成功');
if (title == '添加产品信息') {
// const response = await addUser(values);
// if (response.status === undefined) {
// message.success('添加成功');
// //刷新表格数据
// actionRef.current?.reload();
// isShowModal(false);
// }
// const responses = await updateAvatar({avatar:values.avatar})
// console.log('头像responses:',responses);
} else {
// const response = await updateUser(editId, values);
// if (response.status === undefined) {
// message.success('修改成功');
// //刷新表格数据
// actionRef.current?.reload();
// formObj.resetFields();
// isShowModal(false);
// }
}
};
return (
<Modal
title={title}
open={isModalVisible}
footer={null}
onCancel={() => isShowModal(false)}
destroyOnClose={true}
>
<ProForm
form={formObj}
initialValues={initialValues}
onFinish={(values) => createUser(values)}
>
<ProFormText
name="name"
label="产品名称"
placeholder="请输入产品名称"
rules={[
{
required: true,
message: '请输入产品名称',
},
]}
/>
<ProFormText
name="img"
label="图片地址"
placeholder="请输入图片地址"
rules={[
{
required: true,
message: '请输入图片地址',
},
]}
/>
<ProFormText
name="info"
label="产品信息"
placeholder="请输入产品信息"
rules={[
{
required: true,
message: '请输入产品信息',
},
]}
/>
<ProFormText
name="material"
label="产品材料"
placeholder="请输入产品材料"
rules={[
{
required: true,
message: '请输入产品材料',
},
]}
/>
</ProForm>
</Modal>
);
};
export default CreateOrEdit;
到这里,一个简单的页面就创建好了,还需要的就是对接 CRUD 接口