React-Antd Pro增删改查
基础功能无非是增删改查,用于熟悉路由,组件,传值等Antd Pro的常用功能
上文介绍了Antd Pro的基础搭建,再此基础上进行实践
Antd Pro默认版本V5
一.菜单
首先配置左侧菜单列表,文件夹config》config.ts中找到routes:
添加如下内容:
{ path:'/myapp', name:'我的应用', icon:'AppstoreFilled', routes:[ { name:'应用列表', path:'./user/manage', component:'./user/manage' } ], }
结果下图所示:
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020152759995-308206672.png)
二.模块
找到文件夹pages,创建文件夹user,再创建文件夹manage。
然后配置页面,请求,数据模型等。
最后结构如下图所示:
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020152855023-1268528795.png)
components:用于放置页面常用的组件
data.d.ts:用到的数据模型
index.tsx:模块的主页面
service.ts:封装了用到的Api请求函数
这种结构的细分对后期项目维护非常友好,缺点是前期开发速度受影响
(1)准备工作
1.1 封装数据模型data.d.ts
1 export type TableListItem = { 2 id: string; 3 rolename: string; 4 account: string; 5 username: string; 6 }; 7 export type TableListPagination = { 8 total: number; 9 pageSize: number; 10 current: number; 11 };
1.2 封装用到的API请求
在Antd Pro中是通过Mock实现,本篇用.net core Api进行替换,后端代码在下文附件中下载
1 // @ts-ignore 2 /* eslint-disable */ 3 import { request } from 'umi'; 4 import { TableListItem } from './data'; 5 6 /** 获取列表 */ 7 export async function rule( 8 params: { 9 // query 10 /** 当前的页码 */ 11 current?: number; 12 /** 页面的容量 */ 13 pageSize?: number; 14 }, 15 options?: { [key: string]: any }, 16 ) { 17 return request<{ 18 data: TableListItem[]; 19 /** 列表的内容总数 */ 20 total?: number; 21 success?: boolean; 22 }>('http://localhost:4089/User', { 23 method: 'GET', 24 params: { 25 ...params, 26 }, 27 ...(options || {}), 28 }); 29 } 30 31 /** 更新 */ 32 export async function updateRule(data: { [key: string]: any }, options?: { [key: string]: any }) { 33 return request<TableListItem>('http://localhost:4089/User/Update', { 34 data, 35 method: 'PUT', 36 ...(options || {}), 37 }); 38 } 39 40 /** 新建 */ 41 export async function addRule(data: { [key: string]: any }, options?: { [key: string]: any }) { 42 return request<TableListItem>('http://localhost:4089/User/Add', { 43 data, 44 method: 'POST', 45 ...(options || {}), 46 }); 47 } 48 49 /** 删除 */ 50 export async function removeRule(data: { key: string[] }, options?: { key: string[] }) { 51 return request<Record<string,string[]>>('http://localhost:4089/User', { 52 data, 53 method: 'DELETE', 54 ...(options || {}), 55 }); 56 }
(2)列表 index.tsx
实现效果如下:
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020153101431-584907367.png)
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import { PlusOutlined } from '@ant-design/icons'; 2 import { Button, message } from 'antd'; 3 import React, { useState } from 'react'; 4 import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; 5 import type { ProColumns } from '@ant-design/pro-table'; 6 import ProTable from '@ant-design/pro-table'; 7 import { rule, addRule,updateRule,removeRule } from './service'; 8 import type { TableListItem, TableListPagination } from './data';import CreateForm from './components/CreateForm'; 9 import UpdateForm from './components/UpdateForm'; 10 11 12 const handleRemove = async (selectedRows: TableListItem[]) => { 13 const hide = message.loading('正在删除'); 14 if (!selectedRows) return true; 15 console.log( selectedRows); 16 console.log( selectedRows.map((row) => row.id)); 17 try { 18 await removeRule({ 19 key: selectedRows.map((row) => row.id), 20 }); 21 hide(); 22 message.success('删除成功,即将刷新'); 23 return true; 24 } catch (error) { 25 hide(); 26 message.error('删除失败,请重试'); 27 return false; 28 } 29 }; 30 31 const TableList: React.FC = () => { 32 const [visible, setVisible] = useState<boolean>(false); 33 const [current, setCurrent] = useState<Partial<TableListItem> | undefined>(undefined); 34 const [updvisible, setUpdvisible] = useState<boolean>(false); 35 const handleSubmit = (values: TableListItem) => 36 { 37 addRule({ ...values }); 38 message.success('添加成功'); 39 setVisible(false); 40 }; 41 const handleUpdSubmit = (values: TableListItem) => 42 { 43 updateRule({ ...values }); 44 message.success('修改成功'); 45 setUpdvisible(false); 46 }; 47 48 const [selectedRowsState, setSelectedRows] = useState<TableListItem[]>([]); 49 50 const columns: ProColumns<TableListItem>[] = [ 51 { 52 title: 'id', 53 dataIndex: 'id', 54 valueType: 'textarea', 55 hideInForm: true, 56 hideInTable: true 57 }, 58 { 59 title: '角色名称', 60 dataIndex: 'rolename', 61 valueType: 'textarea', 62 }, 63 { 64 title: '用户名', 65 dataIndex: 'username', 66 valueType: 'textarea', 67 }, 68 { 69 title: '账号', 70 dataIndex: 'account', 71 valueType: 'textarea', 72 }, 73 { 74 title: '操作', 75 dataIndex: 'option', 76 valueType: 'option', 77 render: (_, record) => [ 78 <a 79 key="Id" 80 onClick={(e) => { 81 e.preventDefault(); 82 setUpdvisible(true); 83 setCurrent(record); 84 }} 85 > 86 修改 87 </a> 88 ], 89 }, 90 ]; 91 92 return ( 93 <PageContainer> 94 <ProTable<TableListItem, TableListPagination> 95 headerTitle="查询表格" 96 rowKey="id" 97 search={{ 98 labelWidth: 120, 99 }} 100 toolBarRender={( ) => [ 101 <Button 102 type="primary" 103 key="primary" 104 onClick={() => { 105 setVisible(true); 106 }} 107 > 108 <PlusOutlined /> 109 新建 110 </Button> 111 ]} 112 request={rule} 113 columns={columns} 114 rowSelection={{ 115 onChange: (_, selectedRows) => { 116 console.log("选择开始:"+selectedRows.length); 117 setSelectedRows(selectedRows); 118 }, 119 }} 120 /> 121 {selectedRowsState?.length > 0 && ( 122 <FooterToolbar 123 extra={ 124 <div> 125 已选择{' '} 126 <a 127 style={{ 128 fontWeight: 600, 129 }} 130 > 131 {selectedRowsState.length} 132 </a>{' '} 133 项 134 135 </div> 136 } 137 > 138 <Button 139 onClick={async () => { 140 141 await handleRemove(selectedRowsState); 142 setSelectedRows([]); 143 144 }} 145 > 146 批量删除 147 </Button> 148 149 </FooterToolbar> 150 )} 151 <CreateForm 152 done={true} 153 visible={visible} 154 current={current} 155 onSubmit={handleSubmit} 156 onVisibleChange={setVisible} 157 /> 158 <UpdateForm 159 done={true} 160 updvisible={updvisible} 161 current={current} 162 onSubmit={handleUpdSubmit} 163 onVisibleChange={setUpdvisible} 164 /> 165 166 </PageContainer> 167 ); 168 }; 169 170 export default TableList;
ProTable:表格组件,具体使用参考:https://procomponents.ant.design/components/table/
ProColumns:表格列,注意dataIndex属性对应的大小写问题
request={rule}: rule对应到data.d.ts中的列表Api
后端模拟了一些数据用于显示:
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020153257198-1335673123.png)
其中的CreateForm和UpdateForm在下一步会介绍
(3)新增和修改
新增和修改用弹窗的形式显示,弹窗组件ModalForm,可以参考https://procomponents.ant.design/components/modal-form
在Antd Pro中弹窗的关闭和显示 通过其属性visible控制。需要注意的是,要配置参数属性onVisibleChange,否则可能会有弹窗无法关闭的问题
3.1 新增页面
实现效果:
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020153454778-1206630756.png)
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import type {FC} from 'react'; 2 import { 3 ModalForm, 4 ProFormText 5 } from '@ant-design/pro-form'; 6 import type {TableListItem} from '../data.d' 7 type CreateFormProps={ 8 done: boolean; 9 visible: boolean; 10 current: Partial<TableListItem>| undefined; 11 onSubmit: (values: TableListItem) => void; 12 onVisibleChange?: (b: boolean) => void; 13 } 14 15 const CreateForm: FC<CreateFormProps>=(props)=>{ 16 const{done,visible,current,onSubmit,onVisibleChange}=props; 17 if(!visible){ 18 return null; 19 } 20 return ( 21 <ModalForm<TableListItem> 22 visible={visible} 23 title={'添加'} 24 width={640} 25 onFinish={async (values)=>{ 26 onSubmit(values) 27 }} 28 onVisibleChange={onVisibleChange} 29 initialValues={current} 30 modalProps={{ 31 onCancel: () => {return true;}, 32 destroyOnClose:true, 33 bodyStyle:done?{padding:'72px o'}:{} 34 }} 35 > 36 { 37 <> 38 <ProFormText 39 name="rolename" 40 label="角色名称" 41 placeholder="请输入" 42 /> 43 <ProFormText 44 name="account" 45 label="账号名称" 46 placeholder="请输入"/> 47 <ProFormText 48 name="username" 49 label="用户名称" 50 placeholder="请输入"/> 51 </> 52 } 53 54 55 </ModalForm> 56 ); 57 }; 58 export default CreateForm;
点击"确定",触发”onFinish“,调用父组件传来的方法handleSubmit提交数据,参数values拿到需要提交的能映射到data.d.ts中的TableListItem模型数据
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020153624075-1206522497.png)
3.2 修改页面
实现效果:
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020153730880-2077083382.png)
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import type {FC} from 'react'; 2 import { 3 ModalForm, 4 ProFormText 5 } from '@ant-design/pro-form'; 6 import type {TableListItem} from '../data.d' 7 type UpdateFormProps={ 8 done: boolean; 9 updvisible: boolean; 10 current: Partial<TableListItem>| undefined; 11 onSubmit: (values: TableListItem) => void; 12 onVisibleChange?: (b: boolean) => void; 13 14 } 15 16 const UpdateForm: FC<UpdateFormProps>=(props)=>{ 17 const{done,updvisible,current,onSubmit,onVisibleChange}=props; 18 if(!updvisible){ 19 return null; 20 } 21 return ( 22 <ModalForm<TableListItem> 23 visible={updvisible} 24 title={'修改'} 25 width={640} 26 onFinish={async (values)=>{ 27 onSubmit(values) 28 }} 29 onVisibleChange={onVisibleChange} 30 initialValues={current} 31 modalProps={{ 32 destroyOnClose:true, 33 bodyStyle:done?{padding:'72px o'}:{} 34 }} 35 > 36 { 37 <> 38 <ProFormText 39 name="rolename" 40 label="角色名称" 41 placeholder="请输入" 42 /> 43 <ProFormText 44 name="account" 45 label="账号名称" 46 placeholder="请输入"/> 47 <ProFormText 48 name="username" 49 label="用户名称" 50 placeholder="请输入"/> 51 </> 52 } 53 54 55 </ModalForm> 56 ); 57 }; 58 export default UpdateForm;
修改和新增功能类似,多了数据显示的功能,选择后的数据通过current存储
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020153843188-174458736.png)
最后提交至updateform组件的current属性
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020153906901-452838445.png)
(4)删除
主要是针对批量删除,在表格中配置rowSelection,监听和记录选中的项
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020153943519-1817539129.png)
删除接口的传参是Request Payload,后端接收参数的是字典类型,后面还需优化
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020154011732-947308659.png)
Dictionary<string,string[]>接收待删除项
![](https://img2020.cnblogs.com/blog/783110/202110/783110-20211020154032166-102794976.png)
三.总结
以上简单记录了下基于Antd Pro的增删改查功能,涉及到React一些基础知识,比如创建组件,Hook的一些使用,
涉及到了ES6的一些常用函数map,set,async,Promise等,
最主要是Pro中6个基于Antd开发的模板组件,ProLayout,ProTable,ProForm,ProCard,ProDescriptions,ProSkeleton
以上仅用于学习和总结!
附:后端Api
链接:https://pan.baidu.com/s/1_ZAGB-WilXdrxiU9gdn47A
提取码:4m5w