3.1 删除一条数据

3.1.1 给每条数据增加操作功能

首先增加对message组件的引用

  1. -import { Drawer } from 'antd';
  2. +import { Drawer, message } from 'antd';

然后给columns增加一个放操作链接的列定义(放在所有列的最后)

  1. const columns: ProColumns<TYPE.Member>[] = [
  2. ...
  3. {
  4. title: '操作',
  5. valueType: 'option',
  6. align: 'center',
  7. hideInSetting: true,
  8. render: (_, record) => [
  9. <a
  10. key="delete"
  11. onClick={ () => message.info('你点击了【删除】') }
  12. >删除</a>
  13. ],
  14. },
  15. ];

现在数据列表每一行都有删除该行数据的链接
image.png

在数据详细页的右上角也自动出现了删除链接
image.png

3.1.2 实现数据删除的请求及处理

增加新的引用,然后定义一个useRef hook变量

  1. import React, { useState, useRef } from 'react';
  2. import type { ProColumns, ActionType } from '@ant-design/pro-table';
  3. ...
  4. const MemberList: React.FC = () => {
  5. const actionRef = useRef<ActionType>();

把actionRef放到ProTable的属性里

  1. <ProTable<TYPE.Member, TYPE.PageParams>
  2. ...
  3. actionRef = {actionRef}

src/pages/MemberList/index.tsx 的顶层中(函数体外部)定义一个处理删除一条数据的函数

  1. const handleDeleteCurrent = async (id: number) => {
  2. const hide = message.loading('正在删除');
  3. try {
  4. await deleteMember({id: id});
  5. hide();
  6. message.success('删除成功,即将刷新',1);
  7. return true;
  8. } catch (error) {
  9. hide();
  10. message.error('删除失败,请重试');
  11. return false;
  12. }
  13. };

修改删除单行数据的响应函数

  1. onClick={async () => {
  2. await handleDeleteCurrent(record.id as number);
  3. actionRef.current?.reloadAndRest?.();
  4. }}

src/services/api/member.ts中定义deleteMember

  1. export async function deleteMember(params: any) {
  2. const { id } = params;
  3. return request('/api/member/delete', {
  4. method: 'POST',
  5. params: {
  6. id,
  7. }
  8. });
  9. }

把API中的删除功能引用进index.tsx

  1. import { queryAllMember, deleteMember } from '@/services/api/member';

这时删除功能已经可以工作了,但因为服务器端没有实际的删除功能,所以执行结果是失败的
image.png

3.1.3 完成在mock中的模拟响应

mock/member.ts中增加一个函数

  1. function deleteRow(req: Request, res: Response, u: string) {
  2. const { id } = req.query;
  3. memberListDataSource = memberListDataSource.filter( data => data.id != id);
  4. const result = {
  5. success: true,
  6. }
  7. return res.json(result);
  8. }

定义与之对应的网络请求

  1. export default {
  2. 'POST /api/member/delete': deleteRow,

3.2.4 删除前增加一个确认环节

因为删除数据的操作往往比较敏感,为了减少用户误操作的可能,我们在删除给弹出一个气泡确认框让用户进行确认。

首先引入

  1. -import { Drawer, message, } from 'antd';
  2. +import { Drawer, message, Popconfirm } from 'antd';

然后把现有删除一条数据的链接改成如下的代码

  1. <Popconfirm
  2. placement="rightTop"
  3. title={'确实要删除这一条么?'}
  4. onConfirm={async () => {
  5. await handleDeleteCurrent(record.id as number);
  6. actionRef.current?.reloadAndRest?.();
  7. }}
  8. okText="是的"
  9. cancelText="取消"
  10. >
  11. <a key="delete" >删除</a>
  12. </Popconfirm>,d

这时候点击删除,我们会看到如下的气泡对话框
image.png
这个Popconfirm组件没有提供友好的自定义按钮的手段,如果想用链接实现那两个按钮,可以用我们自己定义的PopConfirm组件(注意大小写)。具体需要如下工作:

  • 创建src/components/PopConfirm目录
  • 在目录下创建index.tsx文件
  • 把本教程附件的PopConfirm组件放内容复制到PopConfirm/index.tsx

在pages/MemberList/index.tsx增加引用

  1. import PopConfirm from '@/components/PopConfirm'

删除对Popconfirm的引用,然后吧当前的组使用的件名称改成PopConfirm(注意大小写)

现在这个气泡对话框变成了下面的样子
3. 删除一条或多条数据 - 图5
新的组件多了三个属性:okLinkStyle和cancelLinkStyle分别是两个链接的风格定义,buttonStyle默认为link,把用链接的方式来选择,如果是其他值则继续以前的按钮方式

  1. buttonStyle?: string,
  2. okLinkStyle?: CSSProperties;
  3. cancelLinkStyle?: CSSProperties;

说明:

其实通过局部重载默认的风格定义(主要是.ant-btn.ant-btn-primary.ant-btn-sm也能达到同样的效果,所以自定义这么一个组件其实没太大意义,这么做研究并展示一下参照Ant Design源码自己定义组件的方法。另外,这个组件的代码参见教程附录。

3.2 删除多条数据

3.2.1 增加选中多条数据的功能

定义一个新的state hook存储选中数据的

  1. const [selectedRows, setSelectedRows] = useState<TYPE.Member[]>([]);

ProTable增加一个按行选择的属性

  1. <ProTable<TYPE.Member, TYPE.PageParams>
  2. ...
  3. rowSelection={{
  4. onChange: (_, selectedRows) => {
  5. setSelectedRows(selectedRows);
  6. },
  7. }}

这时候可以看到在每一行前面都出现一个用来选中该行的复选框,并且标题那里有个选中本页全部数据的复选框
image.png

3.2.2 增加批量删除按钮

引用ButtonFooterToolbar

  1. import { Drawer, message, Button} from 'antd';
  2. import { PageContainer, FooterToolbar } from '@ant-design/pro-layout';

ProTable下面放一个FooterToolbar

  1. {selectedRows?.length > 0 && (
  2. <FooterToolbar
  3. extra={
  4. <div>
  5. 已选择{' '}
  6. <a
  7. style={{
  8. fontWeight: 600,
  9. }}
  10. >
  11. {selectedRows.length}
  12. </a>{' '}
  13. </div>
  14. }
  15. >
  16. <Button
  17. onClick={() => message.info('你要批量删除')}
  18. >
  19. 批量删除
  20. </Button>
  21. </FooterToolbar>
  22. )}

image.png

3.2.3 实现批量删除数据的请求及处理

api/member.ts中定义发起网络请求的函数

  1. export async function deleteMemberList(params?: { [list: string]: any }) {
  2. return request<Record<string, any>>('/api/member/deleteList', {
  3. method: 'POST',
  4. params: {
  5. ...params,
  6. }
  7. });
  8. }

在index.ts中引用api/member.ts中新定义的函数

  1. import { queryAllMember, deleteMember,deleteMemberList } from '@/services/api/member';

index.ts顶层(函数体外)定义处理函数

  1. const handleDeleteList = async (selectedRows: TYPE.Member[]) => {
  2. const hide = message.loading('正在删除');
  3. if (!selectedRows) return true;
  4. try {
  5. await deleteMemberList({
  6. list: selectedRows.map((row) => row.id),
  7. });
  8. hide();
  9. message.success('删除成功,即将刷新');
  10. return true;
  11. } catch (error) {
  12. hide();
  13. message.error('删除失败,请重试');
  14. return false;
  15. }
  16. };

修改批量删除按钮的响应函数

  1. <Button
  2. onClick={async () => {
  3. await handleDeleteList(selectedRows);
  4. setSelectedRows([]);
  5. actionRef.current?.reloadAndRest?.();
  6. }}
  7. >

同样的,因为服务器没有实现对应的响应处理,点击批量删除按钮会得到出错的提示
image.png

3.2.4 完成在mock中的模拟响应

在mock/member.ts中定义下面这个函数

  1. function deleteList(req: Request, res: Response, u: string) {
  2. const { list } = req.query;
  3. const idList = (list as string[]).map( id => parseInt(id))
  4. memberListDataSource = memberListDataSource.filter( data => !idList.includes(data.id as number));
  5. const result = {
  6. success: true,
  7. }
  8. return res.json(result);
  9. }

把他对应请求链接并导出

  1. export default {
  2. 'POST /api/member/deleteList': deleteList,

现在我们可以看到批量删除的效果了

3.2.5 删除前增加一个确认环节

因为删除数据的操作往往比较敏感,为了减少用户误操作的可能,我们在删除给弹出一个模态对话框让用户进行确认。

首先引用Modal和一个icon

  1. -import { Drawer, message, Button } from 'antd';
  2. +import {Drawer, message, Button, Modal } from 'antd';
  3. +import { ExclamationCircleOutlined } from '@ant-design/icons';

然后把“批量删除”按钮的响应函数改成如下的内容

  1. onClick={async () => {
  2. Modal.confirm({
  3. title: '删除提示',
  4. icon: <ExclamationCircleOutlined />,
  5. content: '你确实要删除这些选中的数据么?',
  6. okText: '是的',
  7. okType: 'danger',
  8. cancelText: '不了',
  9. onOk: async () => {
  10. await handleDeleteList(selectedRows);
  11. setSelectedRows([]);
  12. actionRef.current?.reloadAndRest?.();
  13. },
  14. onCancel() {},
  15. });
  16. }}

这时候点击按钮会得到这样一个对话框
image.png

版权说明:本文由北京朗思云网科技股份有限公司原创,向互联网开放全部内容但保留所有权力。